etw事件定义必须用event_descriptor完整初始化,version为0,channel、level、opcode、task不可遗漏;provider需正确注册并保存reghandle;字符串须用event_data_descriptor封装;高频场景应先调用eventenabled判断。

ETW 事件定义必须用 EVENT_DESCRIPTOR 初始化,不能只填 Id
Windows ETW 不接受“半初始化”的事件描述符。常见错误是只设 Id,漏掉 Version、Channel、Level、Opcode 和 Task,结果 EventWrite 返回 ERROR_INVALID_PARAMETER 或静默失败。
-
Version必须为0(当前唯一有效值) -
Channel推荐用CHANNEL_TRACE_LOGGING(自定义提供者)或CHANNEL_KERNEL_TRACE(内核事件) -
Level常用LEVEL_VERBOSE(5)、LEVEL_INFORMATIONAL(4)、LEVEL_WARNING(3) -
Opcode对应操作类型,如OPCODE_START/OPCODE_STOP/OPCODE_INFO,影响 WPA 解析时的图标和分组
示例:
EVENT_DESCRIPTOR desc = { 1, 0, 0, 4, 0, 0, 0 }; // Id=1, Level=4 (INFO), 其余字段显式置 0
Provider 注册要调用 EventRegister,且必须检查返回值
没注册就写事件,EventWrite 直接返回 ERROR_NOT_FOUND。但更隐蔽的问题是:注册成功后没保存返回的 REGHANDLE,后续写事件传入无效句柄,行为未定义(常 crash 或丢事件)。
- 注册前确保
EventRegister的回调函数(EnableCallback)已正确定义,哪怕空实现也要存在 - 注册失败时(如权限不足、提供者 GUID 冲突),
EventRegister返回非零值,必须判断,不能忽略 -
REGHANDLE是全局生命周期变量,不要在函数栈上声明后传出
典型误写:
REGHANDLE h; EventRegister(&MyProviderGuid, EnableCallback, nullptr, &h); // 忘记检查返回值
字符串参数必须用 EVENT_DATA_DESCRIPTOR + EventDataDescCreate 封装,不能直接传指针
ETW 要求所有数据通过 EVENT_DATA_DESCRIPTOR 数组传递,字符串尤其容易错:直接传 const char* 地址会导致读取越界或乱码,因为 ETW 不知道长度。
- 对 UTF-8 字符串,用
EventDataDescCreate(&desc, (PVOID)str, (ULONG)strlen(str)) - 对宽字符串(
LPCWSTR),长度按字节算:sizeof(WCHAR) * wcslen(str) - 多个参数需构造数组,
EventWrite第三个参数是Count,不是单个 descriptor
正确示例:
char msg[] = "startup complete"; EVENT_DATA_DESCRIPTOR descs[2]; EventDataDescCreate(&descs[0], (PVOID)msg, (ULONG)strlen(msg)); EventDataDescCreate(&descs[1], &duration_ms, sizeof(duration_ms)); EventWrite(hProvider, &g_MyEventDescriptor, 2, descs);
性能敏感路径中避免频繁调用 EventWrite,尤其带字符串或堆分配
每次 EventWrite 至少触发一次内核态拷贝,高频打点(如每帧、每循环)会显著拖慢程序,尤其在低优先级线程或高负载机器上。
- 启用前先用
EventEnabled判断当前 session 是否启用了该 level+keyword,跳过无用调用 - 避免在锁内、中断上下文、实时音频线程里写事件
- 字符串拼接(如
std::to_string+.c_str())隐含堆分配,高频场景改用栈缓冲 +_itoa_s等无分配转换 - WPA 中若看到大量
Microsoft-Windows-Kernel-TraceControl事件干扰主线程,大概率是 ETW 打点太密
关键点:ETW 本身不慢,慢的是你没控制好采样节奏和数据规模。真正卡住的从来不是 trace,而是没想清楚「这里到底要不要记」。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











