PENABLECALLBACK 回调函数 (evntprov.h)
ETW 事件提供程序(可选)定义 EnableCallback 函数以接收配置更改通知。 PENABLECALLBACK 类型定义指向此回调函数的指针。 EnableCallback 是应用程序定义的函数名称的占位符。
语法
PENABLECALLBACK Penablecallback;
void Penablecallback(
[in] LPCGUID SourceId,
[in] ULONG IsEnabled,
[in] UCHAR Level,
[in] ULONGLONG MatchAnyKeyword,
ULONGLONG MatchAllKeyword,
[in, optional] PEVENT_FILTER_DESCRIPTOR FilterData,
[in, optional] PVOID CallbackContext
)
{...}
参数
[in] SourceId
由启用或禁用提供程序的调用方指定的 GUID。
该值来自 EnableTraceEx 的 SourceId 参数或传递给 EnableTraceEx2的ENABLE_TRACE_PARAMETERS的 SourceId 字段。
注意
SourceId 是在调用 EnableTraceEx 或 EnableTraceEx2 API 时指定的会话值。 它可能与会话的 GUID 相同,也可能不同。
在通知没有源标识符的几种方案中,SourceId 将设置为 GUID_NULL。 例如,当跟踪会话在提供程序启动之前启用了提供程序、提供程序停止或跟踪控制器在未指定 SourceId 的情况下调用 EnableTrace API 时,可能会发生这种情况。
[in] IsEnabled
指示与此通知对应的 ControlCode。 这可以是以下值之一:
Value | 含义 |
---|---|
EVENT_CONTROL_CODE_DISABLE_PROVIDER (0) | 没有会话启用提供程序。 |
EVENT_CONTROL_CODE_ENABLE_PROVIDER (1) | 一个或多个会话已启用提供程序。 |
EVENT_CONTROL_CODE_CAPTURE_STATE (2) | 会话请求提供程序记录其状态信息。 提供程序通常通过写入包含提供程序状态的事件来响应。 |
注意
IsEnabled 的值可能与传递给触发此事件的 EnableTrace API 的 ControlCode 不同。 例如,如果两个会话已启用此提供程序,一个会话通过调用 EnableTraceEx2(..., EVENT_CONTROL_CODE_DISABLE_PROVIDER, ...)
禁用此提供程序,则提供程序将收到 IsEnabled 设置为 EVENT_CONTROL_CODE_ENABLE_PROVIDER
的通知,因为该提供程序仍由另一个会话启用。
收到 DISABLE_PROVIDER 通知后,提供程序可以通过禁用所有事件来优化其性能。 收到 ENABLE_PROVIDER 通知后,提供程序应启用写入事件。 它还可以通过记录 Level、MatchAnyKeyword 和 MatchAllKeyword 筛选器的值来优化其性能,然后仅将传递筛选器的事件写入 (,如 备注) 中所述。 收到 CAPTURE_STATE 通知后,提供程序可能会采取任何看起来合适的操作,通常编写描述组件配置或状态的事件。
提供程序应忽略其无法识别或不支持的 IsEnabled 值的通知。
[in] Level
一个 值,该值指定提供程序应写入的事件的详细程度。 当使用控制代码 EVENT_CONTROL_CODE_ENABLE_PROVIDER调用时,提供程序应记录 Level 值,并随后应跳过事件的详细级别大于录制的 Level 的事件,即仅当以下情况下才写入事件:
eventDescriptor.Level <= recorded.Level
通知中的级别是跟踪控制器在使用此事件提供程序的 GUID 调用 EnableTrace、EnableTraceEx 或 EnableTraceEx2 时指定的最大级别。 换句话说,如果多个会话以不同的详细级别记录来自此事件提供程序的事件,EnableCallback 通知的 Level 参数将设置为级别的最高 (最详细) 。
[in] MatchAnyKeyword
一个位掩码值,该值指定提供程序应写入的事件类别。 当使用控制代码EVENT_CONTROL_CODE_ENABLE_PROVIDER调用时,提供程序应记录 MatchAnyKeyword 值,并随后应跳过事件,其中事件的关键字 (keyword) 不为零,并且没有记录的 MatchAnyKeyword 中的任何位,即只应在以下情况下写入事件:
eventDescriptor.Keyword == 0 || (eventDescriptor.Keyword & recorded.MatchAnyKeyword) != 0
通知中的 MatchAnyKeyword 是 match-any-keyword 的联合 (或) , (启用此事件提供程序 GUID 的 EnableTrace、EnableTraceEx 和 EnableTraceEx2 调用中由跟踪控制器指定的标志) 。 换句话说,如果多个会话使用不同的 match-any-关键字 (keyword) 筛选器从此事件提供程序记录事件,则 EnableCallback 通知的 MatchAnyKeyword 参数将设置为会话的 match-any-关键字 (keyword) 筛选器的按OR
位。
MatchAllKeyword
一个位掩码值,该值指定提供程序应写入的事件类别。 当收到控制代码EVENT_CONTROL_CODE_ENABLE_PROVIDER的通知时,提供程序应记录 MatchAllKeyword 值,然后应跳过事件关键字 (keyword) 不为零且没有记录的 MatchAllKeyword 中的所有位的事件,即只应在以下情况下写入事件:
eventDescriptor.Keyword == 0 || (eventDescriptor.Keyword & recorded.MatchAllKeyword) == recorded.MatchAllKeyword
通知中的 MatchAllKeyword 是跟踪控制器在此事件提供程序的 GUID 调用 EnableTraceEx 和 EnableTraceEx2 时指定的 match-all-keywords 的析构 (和) 。 换句话说,如果多个会话使用不同的匹配全关键字 (keyword) 筛选器记录来自此事件提供程序的事件,则 EnableCallback 通知的 MatchAllKeyword 参数将设置为会话的所有匹配关键字 (keyword) 筛选器的按AND
位。
[in, optional] FilterData
指向 EVENT_FILTER_DESCRIPTOR 的指针,其中包含事件提供程序的筛选器数据。
每个会话只能指定一个筛选器。 回调通知中的筛选器描述符将包含启用提供程序时指定筛选器数据的每个会话中的一个筛选器。
筛选器数据仅在回调中有效。 如果在回调返回后需要数据,提供程序应创建数据的本地副本。
[in, optional] CallbackContext
回调的上下文。 这是在事件提供程序调用 EventRegister 时使用的 CallbackContext 参数的值。
返回值
无
备注
需要配置更改通知的 ETW 事件提供程序应在通过 EventRegister 注册时提供指向其 EnableCallback 实现的指针。 当更改涉及提供程序的跟踪会话的配置时,ETW 将调用提供程序的 EnableCallback 函数。 例如,当跟踪会话控制器通过 EnableTraceEx2 配置跟踪或通过 ControlTrace 停止跟踪时,ETW 将使用生成的更新配置调用提供程序的 EnableCallback 函数。
注意
大多数事件提供程序不会直接实现 EnableCallback 。 相反,大多数事件提供程序都是使用 ETW 框架实现的,该框架提供自己的 EnableCallback 实现,并包装对 EventRegister、 EventWrite 和 EventUnregister 的调用。 例如,可以 编写事件清单 ,然后使用 消息编译器 为事件生成 C/C++ 代码,或者使用 TraceLogging 来避免需要清单。 ETW 框架通常实现 一个 EnableCallback 函数,该函数记录通知的 Level
、 MatchAnyKeyword
和 MatchAllKeyword
值,框架会自动使用记录的值来筛选事件。 如果用户需要自定义通知处理,ETW 框架通常支持调用用户提供的回调。 例如, TraceLoggingProvider.h 允许通过 TraceLoggingRegisterEx 指定通知回调。
重要
提供程序的 EnableCallback 函数应尽可能简单。 它应记录所需的信息并快速返回。 长时间运行的回调函数可能会导致 ETW 会话控制 API(如 EnableTraceEx2 或 ControlTrace)出现延迟。 回调函数不得执行需要进程加载程序锁的任何操作,即不得直接或间接调用 LoadLibrary 或 FreeLibrary。 回调函数不得阻止锁。 如果回调函数在锁上阻止或调用任何 ETW 会话控制 API(如 StartTrace、 ControlTrace 或 EnableTrace),则可能会导致死锁。
通知回调允许事件提供程序更高效地运行,因为提供程序可以执行自己的级别、关键字和其他筛选器跟踪。 通过跟踪筛选器,提供程序可以有效地跳过未启用 (的事件,即提供程序不需要为) 的任何跟踪会话不需要的事件准备事件数据或调用 EventWrite 。
请注意,提供程序的正确操作不需要筛选器跟踪:ETW 提供提供程序可以使用的 EventEnabled 和 EventProviderEnabled 函数,ETW EventWrite API 将以无提示方式忽略任何已禁用的事件。 但是,提供程序实现的筛选器跟踪可能比调用 EventEnabled 或 EventProviderEnabled 更高效。
通知回调还允许提供程序处理来自跟踪会话的“捕获状态”请求。 捕获状态请求通常在跟踪会话开始记录来自提供程序的事件时发送。 如果提供程序支持捕获状态,则它可能会通过记录状态信息(例如配置信息或请求之前有关组件操作的摘要统计信息)来响应捕获状态请求。
ETW 传递给回调的 Level 值是任何正在运行的跟踪会话为此事件提供程序指定的最高 (最详细) 级别值。 例如,如果会话 A 为警告 (级别 3) 事件启用此提供程序,然后会话 B 为关键 (级别 1) 事件启用该提供程序,则回调的 Level 值为 3,而不是 1。
同样, MatchAnyKeyword 和 MatchAllKeyword 值是从已启用事件提供程序的所有会话的配置中计算的复合值。 MatchAnyKeyword 是会话的 EnableFlags/MatchAnyKeyword 设置的 OR。 MatchAllKeyword 是会话的 MatchAllKeyword 设置的 AND。
如果提供程序的 EnableCallback 函数已捕获提供程序的 Enabled、Level、MatchAnyKeyword 和 MatchAllKeyword 状态,则提供程序可以确定是否应使用如下所示的函数写入事件:
BOOL MyProviderEventEnabled(
_In_ const MY_PROVIDER_STATE* pProvider,
_In_ const EVENT_DESCRIPTOR* pEvent)
{
return
pProvider->Enabled &&
pEvent->Level <= pProvider->Level &&
(pEvent->Keyword == 0 || (
(pEvent->Keyword & pProvider->MatchAnyKeyword) != 0 &&
(pEvent->Keyword & pProvider->MatchAllKeyword) == pProvider->MatchAllKeyword
));
}
要求
最低受支持的客户端 | Windows Vista [仅限桌面应用] |
最低受支持的服务器 | Windows Server 2008 [仅限桌面应用] |
目标平台 | Windows |
标头 | evntprov.h |