ETW (Event Tracing For Windows) – what it is and useful tools
Event Tracing for Windows is the standard way to trace used by all features of Windows. Like the article Improve Debugging And Performance Tuning With ETW explains, ETW is
“a general-purpose, high-speed tracing facility provided by the operating system. Using a buffering and logging mechanism implemented in the kernel, ETW provides a tracing mechanism for events raised by both user-mode applications and kernel-mode device drivers. Additionally, ETW gives you the ability to enable and disable logging dynamically, making it easy to perform detailed tracing in production environments without requiring reboots or application restarts. The logging mechanism uses per-processor buffers that are written to disk by an asynchronous writer thread. This allows large-scale server applications to write events with minimum disturbance.”
The article above explains the ETW architecture (that suffered great improvements since Windows Vista), explaining events and sessions, event providers and event consumers. As a quick overview: an event provider writes events to ETW sessions (it can be any user-mode application, managed application, driver etc). When events are written, ETW adds more info about the time it took place, process and thread ID that generated it, processor number, and CPU usage data of the logging thread. This info is used by the event consumers - application that reads log files or listens to a session for real time events and processes them. More about providers at ETW Trace Providers - When to use what.
Since Windows Vista, the event provider APIs are simpler to use and offer richer functionality (like same way to use trace and event logs). To register as an ETW provider, software components need to provide a GUID as a unique identifier and a callback that will be invoked when notifications are enabled. When enabling a provider, a controller can specify
- a level (1-byte integer) – used to show the severity or verbosity of events (eg. verbose, info, error, critical)
- keywords (8-byte bit masks) – indicate subcomponents in a provider, so subcomponents can be enabled separately.
.Net Framework offers a managed ETW provider API (see System.Diagnostics.Eventing Namespace).
Once a provider is installed, users can collect events from the provider using the logman tool or Reliability and Performance Monitor (Perfmon in Vista and above). The Event Viewer offers another means for collecting and viewing events. Logman is a controller that offers the following options:
logman create - Create a counter, trace, configuration data collector, or API.
logman query - Query data collector properties.
logman start | stop - Start or stop data collection.
logman delete - Delete an existing data collector.
logman update - Update the properties of an existing data collector.
logman import | export - Import a data collector set from an XML file or export a data collector set to an XML file.
To read more about logman, try Two Minute Drill: LOGMAN.EXE.
Tracerpt can be used to process event trace logs or real-time data from instrumented event trace providers. It generates trace analysis reports and CSV (comma-delimited) files for the events generated. LogParser 2.2 also knows to parse ETW events.
To see an example of how to use ETW, read Capturing and analyzing an ETW Trace article.
The tools I mentioned so far are useful to get and analyze the traces. From a developer point of view, if you want to generate traces for your software application, you can create a trace source and then write events to it. Using an ETW listener offers huge performance improvements over other trace listeners. For a managed application that uses the existing trace listeners or other custom listeners, the only change is to switch to the EventProviderTraceListener (a configuration change). For a provider with GUID 4a632b62-b345-42d4-56dc-g1sac9hfjr14 (generated and installed by you), the config file can look like this:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.diagnostics> <sources> <source name="MySourceName" switchName="mySwitch" switchType="System.Diagnostics.SourceSwitch"> <listeners> <remove name="Default" /> <add name="MyEventProviderTraceListener" type="System.Diagnostics.Eventing.EventProviderTraceListener, System.Core, Version=184.108.40.206, Culture=neutral, PublicKeyToken=b77a5c561934e089" initializeData="4a632b62-b345-42d4-56dc-g1sac9hfjr14" /> </listeners> </source> </sources> <trace autoflush="true" indentsize="4"/> </system.diagnostics> </configuration>
But more about this in a future post. Stay tuned!