![]() |
VOOZH | about |
dotnet add package Nefarius.Utilities.ETW --version 2.17.0
NuGet\Install-Package Nefarius.Utilities.ETW -Version 2.17.0
<PackageReference Include="Nefarius.Utilities.ETW" Version="2.17.0" />
<PackageVersion Include="Nefarius.Utilities.ETW" Version="2.17.0" />Directory.Packages.props
<PackageReference Include="Nefarius.Utilities.ETW" />Project file
paket add Nefarius.Utilities.ETW --version 2.17.0
#r "nuget: Nefarius.Utilities.ETW, 2.17.0"
#:package Nefarius.Utilities.ETW@2.17.0
#addin nuget:?package=Nefarius.Utilities.ETW&version=2.17.0Install as a Cake Addin
#tool nuget:?package=Nefarius.Utilities.ETW&version=2.17.0Install as a Cake Tool
👁 .NET
👁 Requirements
👁 Windows only
👁 NuGet Version
👁 NuGet
👁 Assisted by Cursor AI
ETW Log Files (.ETL) to JSON parser/converter library.
This is a fork of the fantastic ETW2JSON project by Microsoft and
contributors.
While this library is designed to support universal ETW trace sources, the primary personal goal and highest development priority has been making it work reliably with WPP Software Tracing in particular. Other trace source types may work but receive less focused attention and testing.
Nefarius.Utilities.ETW to avoid conflicts with the origin library.PDB files as a decoding source — WPP provider GUIDs (ETW trace control GUIDs) are automatically extracted from TMC: annotations in the PDB symbol stream so no manual GUID lookup is required.TMF files as a decoding source%!FUNC!, %!LEVEL!, %!FLAGS!, %!IPADDR!, %!TIMESTAMP!, %!delta!, %!due!, %!GUID!,
%!CLSID!/%!LIBID!/%!IID!, %!PORT!, %!STATUS!, %!WINERROR!, %!HRESULT!,
%!NDIS_STATUS!, %!NDIS_OID!, %!sid!, bitset/list enumerations, and more)USEPREFIX/USESUFFIX trace message prefixes are automatically expanded — the %0 standard-prefix
sentinel and %!FUNC!/%!LEVEL! context markers are resolved from the TMF metadata at decode timeEtwUtil.EnumeratePdbReferences for lightweight pre-scanning of ETL files to collect all PDB metadata
(symbol GUIDs, ages and file names) referenced in the trace before performing a full decode — enabling
proper multi-PDB symbol resolution via symbol servers or local pathsEtwUtil.EnumerateEventsAsync — a streaming IAsyncEnumerable<ReadOnlyMemory<byte>> API that
yields each decoded ETW event as a self-contained UTF-8 JSON buffer as it is produced, rather than
waiting for the full trace to finish; a dedicated background thread runs the blocking ProcessTrace call
and feeds a bounded channel so the consumer is naturally backpressured and can process events concurrently
with parsing; works well as a data source for real-time delivery scenarios such as
FastEndpoints Server Sent Events:public override async Task HandleAsync(CancellationToken ct)
{
await Send.EventStreamAsync("etw-event", GetEtwStream(ct), ct);
}
private async IAsyncEnumerable<object> GetEtwStream([EnumeratorCancellation] CancellationToken ct)
{
await foreach (ReadOnlyMemory<byte> eventJson in EtwUtil.EnumerateEventsAsync(
[@"C:\traces\capture.etl"],
opts => opts.WppDecodingContext = myDecodingContext,
ct))
{
yield return JsonSerializer.Deserialize<object>(eventJson.Span)!;
}
}
EtwRealtimeSession and EtwUtil.EnumerateRealtimeEventsAsync:
EtwRealtimeSession.Create(name) starts a user-mode ETW session (StartTraceW)EnableProvider / DisableProvider toggle providers at runtime via EnableTraceEx2EtwUtil.EnumerateRealtimeEventsAsync attaches to any externally-managed session and streams decoded events as UTF-8 JSON using the same bounded-channel / background-thread architecture as the file-based EnumerateEventsAsyncEtwUtil.ConvertRealtimeToJson blocks and writes events to a Utf8JsonWriter until cancelledEtwUtil.StopOrphanSession cleanly stops a session left behind by a previous crashThe library ships two independent layers for realtime ETW consumption.
If the session is already running (started by logman, xperf, another process, or your own code), attach directly with a session name:
using CancellationTokenSource cts = new();
// Cancel after Ctrl+C or when your app shuts down.
Console.CancelKeyPress += (_, e) => { e.Cancel = true; cts.Cancel(); };
await foreach (ReadOnlyMemory<byte> eventJson in EtwUtil.EnumerateRealtimeEventsAsync(
"MySession",
cancellationToken: cts.Token))
{
Console.WriteLine(System.Text.Encoding.UTF8.GetString(eventJson.Span));
}
Use EtwRealtimeSession when your application owns the session lifetime.
Requires administrator / SeSystemProfilePrivilege.
// Clean up any orphan from a previous crash.
EtwUtil.StopOrphanSession("MyApp-Live");
using EtwRealtimeSession session = EtwRealtimeSession.Create("MyApp-Live",
opts =>
{
opts.BufferSizeKb = 64;
opts.FlushTimerSeconds = 1;
opts.ClockResolution = EtwClockResolution.QueryPerformanceCounter;
});
// Enable one or more providers at the desired verbosity level.
Guid microsoftWindowsKernelProcess = new("22FB2CD6-0E7B-422B-A0C7-2FAD1FD0E716");
session.EnableProvider(microsoftWindowsKernelProcess, TraceEventLevel.Information);
using CancellationTokenSource cts = new();
Console.CancelKeyPress += (_, e) => { e.Cancel = true; cts.Cancel(); };
await foreach (ReadOnlyMemory<byte> eventJson in EtwUtil.EnumerateRealtimeEventsAsync(
session.SessionName,
cancellationToken: cts.Token))
{
Console.WriteLine(System.Text.Encoding.UTF8.GetString(eventJson.Span));
}
// Disposing session calls ControlTraceW(STOP) — no orphan left behind.
EtwRealtimeSession.Create throws EtwStartTraceException with ERROR_ACCESS_DENIED when the process is not elevated.EtwRealtimeSession, and call EtwUtil.StopOrphanSession("name") at startup as a safety net.DecodingContext. The file-based EnumeratePdbReferences pre-scan only works on .etl files, not on live sessions. Build the DecodingContext from known .pdb or .tmf paths before starting the session.etwutils)The tools/Nefarius.Utilities.ETW.CLI project builds a .NET global tool (etwutils) that wraps the realtime API and writes decoded events as NDJSON or plain tab-separated text to stdout.
dotnet tool install -g Nefarius.Utilities.ETW.CLI
See for full installation instructions, command reference, and examples.
%!ItemEnum!/%!ItemFlagsEnum! types display raw numeric values; PDB-based enum name resolution is not yet implemented.
enum _TDH_CONTEXT_TYPE| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0-windows8.0 net8.0-windows8.0 is compatible. net9.0-windows net9.0-windows was computed. net9.0-windows8.0 net9.0-windows8.0 is compatible. net10.0-windows net10.0-windows was computed. net10.0-windows8.0 net10.0-windows8.0 is compatible. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.17.0 | 85 | 6/16/2026 |
| 2.16.0 | 80 | 6/16/2026 |
| 2.15.1 | 97 | 6/1/2026 |
| 2.15.0 | 96 | 6/1/2026 |
| 2.14.2 | 90 | 5/31/2026 |
| 2.14.1 | 94 | 5/31/2026 |
| 2.14.0 | 92 | 5/30/2026 |
| 2.13.0 | 95 | 5/30/2026 |
| 2.12.0 | 108 | 5/29/2026 |
| 2.11.0 | 105 | 5/28/2026 |
| 2.10.2 | 106 | 5/28/2026 |
| 2.10.1 | 95 | 5/28/2026 |
| 2.10.0 | 108 | 5/28/2026 |
| 2.9.0 | 115 | 5/28/2026 |
| 2.8.0 | 127 | 5/27/2026 |
| 2.7.0 | 114 | 5/26/2026 |
| 2.6.0 | 112 | 5/26/2026 |
| 2.5.0 | 111 | 5/26/2026 |
| 2.4.1 | 107 | 5/26/2026 |
| 2.4.0 | 115 | 5/26/2026 |