ET4W – generate C# ETW classes from JSON event specifications using T4

2 minute read


Event Tracing for Windows (ETW) is the best tracing solution for the Windows platform, period. It is unmatched in performance and reliability. More and more tools are built to analyze its events to amazing depth. Microsoft explicitly recommends it for almost any logging purpose.

Unfortunately, writing proper ETW classes is a bit tricky. It used to be much worse (before the advent of automatic manifest generation), but there’s still a lot of code that has to be written manually in a very specific way. Not only is it tedious, it also leaves plenty of room for user error.

  • You have to decorate each event method with EventAttribute (theoretically optional, but in practice you’ll do this for every single method).
  • You then have to call WriteEvent in a very specific manner – the event ID and parameters must match exactly and in order.
  • Tasks and keywords should be specified using nested classes with a very specific structure.
  • You are encouraged to expose the class in a very specific singleton pattern.
  • You must be aware of the exact types supported by ETW (not documented anywhere, so you have to reflect it off ManifestBuilder.GetTypeName).
  • If you want to log types that aren’t supported, it’s your responsibility to invoke the appropriate conversions (typically via manually created wrapper classes).
  • If you want some common parameters to be present in every event, you have to add them manually to each method, and provide them manually in each call.

Enter ET4W.

This T4 Text Templete based NuGet package will solve all these issues for you. All you have to do is write a JSON file specifying the events you want, as well as the custom types you want to support and the common parameters you want present. There’s even a JSON schema for in-editor validation and auto-completion (supported in Visual Studio and other editors).

ET4W will take care of the rest, creating full-fledged EventSource classes according to all the best practices (both System.Diagnostics.Tracing and Microsoft.Diagnostics.Tracing are supported). In addition, wrapper classes are created to support common parameters and custom types. Finally, a few extra validations are thrown into the mix.

Check it out! (Apache 2.0)

P.S. one of the nice thing about this approach is that it lends itself well to cross-platform event consistency. By building similar generation scripts for other languages (VB, C++, etc), you could leverage the same event JSON to maintain a “single source of truth” for your events across various platforms (critical for telemetry measurements, for example).

Leave a Comment