Event Tracing for Windows (ETW) is a logging infrastructure for Windows primarily used in diagnostic and performance analyses. Events generated by the ETW infrastructure contain an event header common to all ETW events and a provider defined payload.
Many subsystems in Windows expose ETW providers for better insight into their operations or performance. Using ETW, we can leverage that data to better understand events that occur in the operating system.
There's a number of terms we'll use in this document so let's define them now and get it over with:
- trace provider - A provider is a source of events. A subsystem (e.g. .NET, COM, WinINet) can register one or more providers to produce events for.
- trace session - A trace session is an instance of an ETW trace with one or more providers registered to it. The trace session handles events from all providers enabled on it in semi-chronological order on a single thread. There can be a maximum of 64 traces on the OS, two of which are reserved.
- kernel trace - Certain providers are exposed by kernel components and can only be registered for by kernel traces. These traces are special in that there can only be 8 sessions running, 2 of which are reserved. These trace sessions can only be started with Administrator privileges.
- user trace - The bulk of the available ETW trace providers are user traces which any process can register for.
- manifest - A manifest is used to define the event schema for a given trace provider.
- schema - Each event has a schema associated with it, allowing the process that is handling the event to understand how to unpack the data from the ETW event buffer.
For any application that wishes to consume events from ETW, they follow a basic pattern:
- Create a trace session
- Register one or more providers with the trace session
- For each provider, set the appropriate "any" and "all" flags
- Register a callback
- Start the trace session
- Process events (indefinitely)
- Stop the trace session
This pattern is common to any program listening to ETW traces.
In addition to the overall pattern of listening to traces, there's a common pattern for processing events as well:
- receive event
- get the schema for the event
- parse out the data field of the event you are interested in based on the schema from (2)
All of the steps above for both listening to traces and processing events are wrapped into a more friendly interface via krabsetw.
When you start an ETW trace, as the caller, you're generally responsible for donating a thread to the ETW subsystem for processing events. Each trace session you start requires a thread for processing. A single thread can process a huge number of events from multiple providers so it's not necessary to start multiple trace sessions unless you find that you're missing events.
For example, in the primary application we use krabsetw for, we consume 9 separate user ETW providers on a single trace session of krabsetw. This trace, on a busy machine, processes upwards of 1.5 trillion events per day.
Because you've donated a thread to processing your ETW trace session, your code needs to do as little as possible on the processing thread. When your event callback is invoked, you want to parse out the event and push processing of it to another thread as fast as you can. This ensures you don't drop events from ETW by not dequeuing new events quickly enough from the buffer.
For more detailed information, please see the examples
folder and the in depth guides:
- Event Tracing Sessions
- Primer on ETW usage from Microsoft.
- Configuring and Starting an Event Tracing Session
- Primer on starting ETW sessions.
- Configuring and Starting a SystemTraceProvider Session
- Primer about the special kernel trace sessions.
- Microsoft Message Analyzer
- This tool is incredibly useful for exploring trace providers that are available on your OS.
- WevtUtil
- This tool is part of the operating system and can be used for identify trace provider information and relevant flags for each provider.