Backgrounder on Windows Event Tracing
When it comes to debugging Windows applications or Windows kernel drivers, there are two essential techniques that every software developer wants to use: A debugger and tracing, also known as logging. While choosing a Windows debugger is easy, choosing the right tracing technique is not so obvious. What tracing method do you use? fprintf, OutputDebugString, or DbgPrint? A logging framework such as Pantheios or log4cxx? Perhaps some self-made macros?
What many software developers are not aware of is that Windows ships with an excellent built-in tracing facility called Event Tracing for Windows (ETW). ETW is especially designed for software development, and it is not to be confused with Event Logging, i.e. the messages that can be viewed with the Windows Event Viewer.
ETW has many of the standard features you expect from a good tracing package, such as both real-time consumption or file logging, multiple trace providers and consumers, thread safety, high resolution time stamps, etc. What makes ETW really stand out are features such as kernel-mode driver support, boot time logging, built-in security, and its best-in-class performance.
Also, since ETW is Windows built-in tracing framework, there is an infrastructure that you can leverage, such as both GUI and command-line tools for starting log-sessions and consuming traces. If a customer happens to run into a problem, you can ask your customers to simply run a Windows command to record a trace and sent it to you.
Microsoft provides an extensive set of Windows APIs that deal with ETW, which, for instance, allow you to enable and disable trace provider and trace messages. Per design, the trace message API is not suitable for direct usage in your C or C++ code, as it only accepts a message GUID and a variable list of parameters. Instead, you typically want your tracing function to accept a formatted string, such as used in printf().
In order to make ETW more user-friendly for C and C++ users, Microsoft created the Windows Software Trace Preprocessor (tracewpp), which enables you to use trace message statements containing a formatted string. Prior compilation, the WPP tool will scan your source code for these trace message statements, and it will generate a trace message header file (TMH file) that you need to include in your source file. This header file contains macros that will replace your trace message statement with very efficient code that will call the ETW APIs.
In addition to the tracing code, WPP will emit annotation code that places metadata into your applications .pdb file (the file containing the debug information). The metadata will contain the format string and additional formatting information, so that tools such as TraceView Plus can render the trace messages. It is important to understand that the trace message data, which is consumed real-time or stored in a trace log file, does not contain any formatted strings. Instead, a message GUID and the raw message parameters are stored. The formatting of the trace message is deferred until you view the trace.