Filtering events using WPR
More often than not, we collect bigger trace files than we really need. Even though what we are interested in are just a few types of events from an event provider. Or other times, we want to see the call stacks of just a few events but not the rest from the event provider. Turning on the event provider with stacks without any filtering can result in a ton of events from the provider plus stack-walk events for every event, bloating the trace. That means a few interesting events are buried under a pile of uninteresting events. Not only does the bloated trace make it hard to find the needle in the haystack, but also poses other problems like the growing size of the trace file. Some performance sensitive programs would have problems in reproducing the issue if full events are enabled.
Filtering events is not a new topic. Developers needed to control verbosity of the events and Event Tracing for Windows has been providing event filtering in various ways. Let us find out how to filter the events using WPR.
Basic event filtering using Keyword and Level
The first level of filtering is to set the keyword and level. The event provider can check the keyword and level value and generate events accordingly. This is a simple and efficient way to filter the events. The best thing about this provider-side filtering is the minimal CPU overhead. However, for this simple provider-side filtering to be effective, the events should be organized with keyword and level by the provider. That is why it is highly recommended for event providers to always define keywords for all events and use levels consistently, regardless of whether they are manifested or tracelogging events.
<EventProvider Id="Test_EventProvider_WPR_Status" Name="36b6f488-aad7-48c2-afe3-d4ec2c8b46fa" Level="3"> <!-- Warning, error, and critical level--> <Keywords> <Keyword Value="0x10000"/><!--PerfStatus--> <Keyword Value="0x20000"/><!--DebugStatus--> <Keyword Value="0x40000"/><!--Informational--> </Keywords> </EventProvider>
Event filtering by event IDs and names
Often, filtering by setting keyword and level is not enough. Manifest based events have the ID, whereas tracelogging events have the name. You can use event IDs or names to filter the specific events in or out.
Table EventFilters and EventNameFilters
|By event ID||By event name|
|Event type||Manifest based||Tracelogging|
|WPR element name||<EventFilters>||<EventNameFilters>|
|WPR Example||Recording events from Microsoft-Windows-Win32k everything except event id 164 and 166 <EventProvider Id=”Microsoft-Windows-Win32k” Name=”8c416c79-d49b-4f01-a467-e56d3aa8234c” NonPagedMemory=”true”> <EventFilters FilterIn=”false”> <EventId Value=”164″ /> <EventId Value=”166″ /> </EventFilters> </EventProvider>||Recording events from EventProvider_TraceLogGen with the event name Preset1 and Preset2 with matching keyword.
<EventProvider Id=”EventProvider_TraceLogGen” Name=”3970F9cf-2c0c-4f11-b1cc-e3a1e9958833″> <EventNameFilters FilterIn=”true” Level=”5″> <Keyword Value=”0x10000000000000″/> <EventName Value=”Preset1″/> <EventName Value=”Preset2″/> </EventNameFilters> </EventProvider>
|Available on||Windows 8.1||Windows 10, version 1709 and later.|
Stack filtering by event IDs and names
Same as the event filtering by event IDs and names, you can filter the stack events using event IDs, names, and keyword/level.
Table StackFilters and StackEventNameFilters
|By event ID||By event name||By keyword and level|
|Event type||Manifest based||Tracelogging||Both|
|WPR element name||<StackFilters>||<StackEventNameFilters>||<StackKeywordLevelFilter>|
|WPR Example||Recording stacks for the events from Microsoft-Windows-Win32k everything except event id 164 and 166 <EventProvider Id=”Microsoft-Windows-Win32k” Name=”8c416c79-d49b-4f01-a467-e56d3aa8234c” NonPagedMemory=”true”> < StackFilters FilterIn=”false”> <EventId Value=”164″ /> <EventId Value=”166″ /> </StackFilters > </EventProvider>||Recording stacks for events from EventProvider_TraceLogGen with the event name Preset1 and Preset2 with matching keyword.
<EventProvider Id=”EventProvider_TraceLogGen” Name=”3970F9cf-2c0c-4f11-b1cc-e3a1e9958833″> < StackEventNameFilters FilterIn=”true” Level=”5″> <Keyword Value=”0x10000000000000″/> <EventName Value=”Preset1″/> <EventName Value=”Preset2″/> </StackEventNameFilters > </EventProvider>
|Recording stacks for events only for the keyword and level specified.
<EventProvider Id=”EventProvider_TraceLogGen” Name=”*TraceLogGen”> <StackKeywordLevelFilter FilterIn=”true” Level=”3″> <Keyword Value=”0x10000000000000″/> </StackKeywordLevelFilter> </EventProvider>
|Available on||Windows 8.1||Windows 10, version 1709 and later.||Windows 10, version 1709 and later.|
Event filtering by the process name
You can also filter the events based on the process names. This type of filtering is called scope filtering. The EVENT_FILTER_DESCRIPTOR type is EVENT_FILTER_TYPE_EXECUTABLE_NAME.
<EventProvider Id="EventProvider-Microsoft-Windows-XAML" Name="531a35ab-63ce-4bcf-aa98-f88c7a89e455" ProcessExeFilter="MyApp.exe" />
ETW supports more types of filtering than described here but we introduced ETW event filtering types that are supported in WPR. Keep in mind that provider-side filtering based on the keyword and level or scope filtering based on the process name/PID have almost no impact on system performance. Other kinds of filtering based on payload or attributes other than keyword and level are usually performed after the provider has generated the event and sent to the ETW runtime. This means more impact on the system performance. This kind of filtering is only effective in reducing trace data volume and is not as effective for reducing trace CPU overhead. For more information about the filtering, refer to EVENT_FILTER_DESCRIPTOR structure and EnableTraceEx2 documentation. In case you are wondering if you can use multiple filters for a provider, the answer is yes.
I would have needed that great explanation a few years ago. WPR is severely underdocumented, but these posts help a lot. More details about WPA improvements would be great like what is “Aggregation UI Improvements” in the latest WPA Release? I was not able to get that to work.
You can use event filters also with xperf to start a trace session and use tracelog to filter events of an existing trace session. For .NET Runtime events I frequently use filters which remove much of the overhead of .NET Runtime events which add no value. Most of the time I care about:
– Exception Stack Traces
– Stack Traces (just these JIT events needed to resolve stacks in WPA)
With xperf I can enable stacks for .NET Runtime ETW provider but collect stacks only for exception ETW events. That saves a lot of space.