4个版本
0.1.7 | 2023年4月6日 |
---|---|
0.1.6 | 2023年3月30日 |
0.1.2 | 2021年4月6日 |
0.1.1 | 2020年6月18日 |
#7 in #trace-logging
每月 25次下载
93KB
1K SLoC
支持Windows事件跟踪(ETW)的Rust
提供了 #[trace_logging_provider]
宏,允许你定义用于与 Trace Logging Provider 和 Event Tracing for Windows (ETW) 框架一起使用的 Trace Logging Provider。
此宏仅适用于针对Windows的情况。当针对其他平台时,此宏仍然可以工作,但将生成不执行任何操作的代码。
此框架允许应用程序记录结构化事件,而不是文本字符串。ETW分析工具可以可靠地识别事件中的字段,并将它们视为强类型数据,而不是文本字符串。
要使用 tracing 与 ETW,请参阅 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
生成的代码所调用的库代码。
为您的事件提供程序创建一个新的GUID
您必须为每个事件提供程序分配一个全新的GUID。ETW使用此GUID来识别由您的提供程序生成的事件。Windows包含许多事件提供程序,因此能够仅选择由您的应用程序生成的事件很重要。此GUID还由ETW内部用于识别事件元数据(字段类型),因此您的GUID必须是唯一的。否则,使用相同GUID的冲突来源的事件可能会被错误解释。
有许多工具可以创建GUID,例如
- 在Visual Studio中,在“工具”菜单中选择“创建GUID”。
- 从Visual Studio命令行运行
uuidgen.exe
。 - 在Ubuntu shell中运行
uuidgen
。
许多处理事件的工具都期望提供程序的GUID基于提供程序名称,并且这种技术由Microsoft推荐。生成与这些工具兼容的GUID的方法包括
- PowerShell:
[System.Diagnostics.Tracing.EventSource]::new("YourProviderName").Guid
- Visual Studio 2022: 在“调试”菜单中选择“性能分析器”。点击“事件查看器”旁边的齿轮图标。在“其他提供程序”下输入您的“提供程序名称”,并将“提供程序GUID”自动填写。
- 在TraceView中,从“文件”菜单中选择“创建新日志会话”。选择“手动输入控制GUID或哈希名称”并输入
*
后跟您的提供程序名称(例如,*YourProviderName
)。然后,点击“确定”。在“格式信息源选择”窗口中,选择“自动”并点击“确定”。GUID将显示。 - 有关其他工具和代码,请参阅此StackOverflow帖子
定义事件提供程序及其事件
将特性定义添加到您的源代码中,并使用您刚刚创建的GUID将其注解为 #[trace_logging_provider(guid = "...")]
宏。特性定义仅用作过程宏的输入;特性不会输出到您的crate中,也不能用作正常特性。
ETW提供程序名称,在ETW元数据中,将基于特性名称。这可以通过在提供程序属性中显式指定名称来覆盖,例如 #[trace_logging_provider(name = "YourNameHere")]
在特性定义中,添加方法签名。每个方法签名定义了一个事件类型。每个方法参数定义了事件类型的字段。只支持有限数量的字段类型(以下列出)。
宏#[trace_logging_provider]
消耗特性定义并生成相同名称和相同方法签名的struct
定义。(特性不能作为普通特性使用。)
# use win_etw_macros::trace_logging_provider;
#[trace_logging_provider(guid = "... your guid here ...")]
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>
。
参考
贡献
此项目欢迎贡献和建议。大多数贡献需要您同意贡献者许可协议(CLA),声明您有权并实际上授予我们使用您贡献的权利。有关详细信息,请访问https://cla.opensource.microsoft.com。
当您提交拉取请求时,CLA机器人会自动判断您是否需要提供CLA,并适当地装饰PR(例如状态检查、评论)。只需遵循机器人提供的说明。您只需在整个使用我们CLA的仓库中做一次。
本项目已采用微软开源行为准则。更多信息请参阅行为准则常见问题解答或联系[email protected],如有任何额外问题或评论。
依赖项
约1.7-2.6MB
约43K SLoC