Filtering events using WPR

Sowoon Pyo

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>
EVENT_FILTER_DESCRIPTOR type EVENT_FILTER_TYPE_EVENT_ID EVENT_FILTER_TYPE_EVENT_NAME
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>
EVENT_FILTER_DESCRIPTOR type EVENT_FILTER_TYPE_STACKWALK EVENT_FILTER_TYPE_STACKWALK_NAME EVENT_FILTER_TYPE_STACKWALK_LEVEL_KW
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" />

Summary

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.

 

1 comment

Discussion is closed. Login to edit/delete existing comments.

  • Alois Kraus 0

    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:

    – Exceptions
    – 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.

    	REM Disable GCAllocationTick=10, IncreaseMemoryPressure=200, DecreaseMemoryPressure=201, GCMarkWithType=202 where GCAllocationTick takes nearly 90% of all data of these events.
    	REM MethodJitInliningSucceeded=185, MethodJitInliningFailed=186, JitTailCallSucceeded=188, JitTailCallFailed=189 are also hefty ones if JITed code is encountered.
    tracelog -enableex ClrSession -guid #e13c0d23-ccbc-4e12-931b-d9cc2eee27e4 -matchanykw 0x8099 -stackwalkFilter -in 1 80 -EventIdFilter -out 17 29 82 33 250 251 252 253 256 10 200 201 202 203 185 186 188 189  

Feedback usabilla icon