8个版本
0.1.9 | 2024年2月6日 |
---|---|
0.1.8 | 2023年5月12日 |
0.1.7 | 2023年4月6日 |
0.1.6 | 2023年3月30日 |
0.1.0 | 2020年5月21日 |
#555 在 过程宏 中
每月391次下载
用于 5 crates
125KB
2K SLoC
为Windows事件跟踪(ETW)提供Rust支持
提供 #[trace_logging_provider]
宏,该宏允许您定义一个 跟踪日志提供程序 以与 Windows事件跟踪(ETW) 框架一起使用。
此宏仅在针对Windows时使用。当针对其他平台时,此宏仍然可以工作,但将生成不执行任何操作的代码。
此框架允许应用程序记录结构化事件,而不是文本字符串。ETW分析工具可以可靠地识别您事件中的字段,并将它们作为强类型数据而不是文本字符串处理。
有关如何使用ETW与 tracing 一起的信息,请参阅 tracing-etw。
如何创建和使用事件提供程序
在ETW中,事件提供程序 是一个生成事件的软件对象。《事件控制器》设置事件日志会话,《事件消费者》读取和解释事件数据。此crate侧重于使应用程序能够创建《事件提供程序》。
添加crate依赖项
将这些依赖项添加到您的 Cargo.toml
文件中
[dependencies]
win_etw_macros = "0.1.*"
win_etw_provider = "0.1.*"
win_etw_macros
包含生成事件代码的过程宏。win_etw_provider
包含由 win_etw_macros
生成代码调用的库代码。
定义事件提供程序及其事件
在源代码中添加一个特征定义,并使用 #[trace_logging_provider]
宏进行注释。该宏消费特征定义并生成具有相同名称和相同方法签名的 struct
定义。(该特征 不能 作为普通特征使用。)
#[trace_logging_provider]
pub trait MyAppEvents {}
每个事件提供者 必须 有一个唯一的名称 和 GUID。 ETW 使用此 GUID 来识别由您的提供者生成的事件。Windows 包含许多事件提供者,因此能够选择仅由您的应用程序生成的事件非常重要。此 GUID 还被 ETW 内部用于识别事件元数据(字段类型),因此您的 GUID 必须是唯一的。否则,使用相同 GUID 的冲突来源的事件可能会被错误解释。
指定提供者名称
除非被覆盖,否则 #[trace_logging_provider]
使用特征定义的名称作为 ETW 提供者的名称(例如,上面的示例中的 "MyAppEvents")。要指定不同的名称,请使用 #[trace_logging_provider(name = "MyCompany.MyComponent")]
指定名称。
为事件提供者生成 GUID
如果您未指定 guid
参数,#[trace_logging_provider]
宏将生成一个基于名称的 .NET EventSource
兼容的 GUID。生成的 GUID 与以下 PowerShell 代码生成的 GUID 相同:[System.Diagnostics.Tracing.EventSource]::new("MyCompany.MyComponent").Guid
。此 GUID 可以通过名为 PROVIDER_GUID
的关联常量从您的 Rust 代码中访问(例如,MyAppEvents::PROVIDER_GUID
)。
如果您不希望使用基于名称的 GUID,您可以使用像 uuidgen
这样的工具(可在 Visual Studio 命令行或 Ubuntu Shell 中获得)生成 GUID,并使用 #[trace_logging_provider(guid = "... your guid here ...")]
指定它。
向提供者添加事件
在特征定义中添加方法签名。每个方法签名定义一个 事件类型。每个方法参数定义事件类型的字段。仅支持有限数量的字段类型(以下列举)。
use win_etw_macros::trace_logging_provider;
#[trace_logging_provider(name = "MyCompany.MyComponent")]
pub trait MyAppEvents {
fn http_request(client_address: &SockAddr, is_https: bool, status_code: u32, status: &str);
fn database_connection_created(connection_id: u64, server: &str);
fn database_connection_closed(connection_id: u64);
// ...
}
创建事件提供者实例
初始化时(在你的 fn main()
等),创建事件提供者的一个实例
let my_app_events = MyAppEvents::new();
你的应用程序应只为每个进程创建每个事件提供者一个实例。也就是说,你应该创建你事件提供者的一个实例,并在你的进程中共享它。通常,实例存储在静态变量中,使用懒加载/原子赋值。有许多crate和类型可以支持这种使用模式。
调用事件方法来报告事件
要报告一个事件,请调用事件提供者上定义的方法之一。该方法将调用ETW来报告事件,但没有保证事件被存储或转发;如果事件缓冲区资源稀缺,事件可能会丢失。
my_app_events.client_connected(None, &"192.168.0.42:6667".parse(), false, 100, "OK");
请注意,所有生成的事件方法都有一个添加的第一个参数,options: Option<&EventOptions>
。此参数允许你覆盖每个事件的参数,例如事件级别和事件关联ID。在大多数情况下,你应该传递 None
。
支持的字段类型
只支持有限的一组字段类型。
- 64位以内的整数原语:
i8
,i16
,i32
,i64
,u8
,u16
,u32
,u64
- 浮点数原语:
f32
,f64
- 架构相关的大小:
usize
,isize
。 - 布尔值:
bool
- 所有支持原语切片:
&[u8]
,&[u16]
等。 - 支持的Windows
FILETIME
。类型必须恰好声明为FILETIME
;类型别名或完全限定路径(如winapi::shared::minwindef::FILETIME
)将不起作用。生成的代码中的参数类型将是win_etw_provider::FILETIME
,这是一个在u64
之上的新类型。 std::time::SystemTime
是支持的,但它必须恰好声明为SystemTime
;类型别名或完全限定路径(如std::time::SystemTime
)将不起作用。SockAddr
、SockAddrV4
和SockAddrV6
均受支持。它们必须严格按照所示声明,不能使用完全限定名或类型别名。
如何捕获和查看事件
有多种工具可用于捕获和查看 ETW 事件。最简单的工具是 Windows SDK 中的 TraceView
工具。通常它安装在这个路径:C:\Program Files (x86)\Windows Kits\10\bin\10.0.<xxxxx>.0\x64\traceview.exe
,其中 <xxxxx>
是 Windows SDK 的版本号。
运行 TraceView
,然后选择“文件”,然后“创建新的日志会话”。选择“手动输入 GUID 或哈希名称”并输入您为事件提供者分配的 GUID。点击“确定”。下一个对话框将提示您选择 WPP 格式信息的来源;选择自动并点击“确定”。
此时,TraceView
应该正在捕获事件(您的分配的 GUID)并在实时显示,无论事件由哪个进程报告。
这些工具也可以用来捕获 ETW 事件
- Windows 性能记录器 此工具旨在捕获系统级的事件流。它对于捕获特定事件提供者的事件没有用。
- logman 是一个用于管理事件的命令行工具。
- Tracelog
还有其他工具,如 Windows 性能记录器,可以捕获 ETW 事件。
改进建议
- 更好地处理每个事件的覆盖,而不是使用
Option<&EventOptions>
。
参考
- Windows 事件跟踪(ETW)简化版
- Windows 事件跟踪(ETW)的 TraceLogging
- 记录和查看 TraceLogging 事件
- TraceLoggingOptionGroup
- 提供者特性
- TRACELOGGING_DEFINE_PROVIDER 宏
贡献
此项目欢迎贡献和建议。大多数贡献都需要您同意贡献者许可协议(CLA),声明您有权并且实际上确实授予我们使用您的贡献的权利。有关详细信息,请访问 https://cla.opensource.microsoft.com。
当您提交拉取请求时,CLA 机器人将自动确定您是否需要提供 CLA,并适当装饰 PR(例如,状态检查,注释)。只需按照机器人提供的说明操作。您只需在整个使用我们的 CLA 的所有存储库中这样做一次。
此项目已采用 Microsoft 开源行为准则。有关更多信息,请参阅 行为准则常见问题解答 或通过 [email protected] 联系我们,提出任何额外的问题或评论。
依赖关系
~2MB
~42K SLoC