4

Listing all available ETW events in a .NET application

 1 year ago
source link: https://www.meziantou.net/listing-all-available-etw-events-in-a-dotnet-application.htm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Listing all available ETW events in a .NET application

 04/03/2023

When tracing an application, it can be useful to know which ETW events are available. .NET exposes many events to trace an application as shown in some previous posts (Getting telemetry data from inside or outside a .NET application, or Avoid DNS issues with HttpClient in .NET). It's hard to know which events are available and which ones are actually sent by the application. In this post, I describe how to list all available events in a .NET application by registering a custom EventListener.

The solution is to modify the application to register an EventListener and log all sent events. As the code runs in the application, it has access to all events and can enable all EventSource that send events. The following code snippet shows how to do this:

using System.Collections.Concurrent;
using System.Diagnostics.Tracing;

internal sealed class EventSourceEnumerator : EventListener
{
    public ConcurrentDictionary<string, ConcurrentDictionary<int, EventInfo>> Events { get; } = new();

    public EventSourceEnumerator()
    {
        EventSourceCreated += OnEventSourceCreated;
        EventWritten += OnEventWritten;
    }

    private void OnEventWritten(object? sender, EventWrittenEventArgs e)
    {
        var events = Events[e.EventSource.Name];
        if (events != null)
        {
            if (!events.ContainsKey(e.EventId))
            {
                events.TryAdd(e.EventId, new EventInfo(e.EventId, e.EventName, e.Level, e.PayloadNames?.ToArray() ?? Array.Empty<string>()));
            }
        }
    }

    private void OnEventSourceCreated(object? sender, EventSourceCreatedEventArgs e)
    {
        if (e.EventSource is null)
            return;

        if (!Events.ContainsKey(e.EventSource.Name))
        {
            EnableEvents(e.EventSource, EventLevel.LogAlways);
            Events.TryAdd(e.EventSource.Name, new ConcurrentDictionary<int, EventInfo>());
        }
    }
}

internal sealed record EventInfo(int Id, string? Name, EventLevel Level, string[] PayloadNames);

You can then use the EventSourceEnumerator to list all available events:

using var eventSourceEnumerator = new EventSourceEnumerator();

Console.WriteLine("Hello, World!");
using var httpClient = new HttpClient();
await httpClient.GetStringAsync("https://www.meziantou.net");

foreach (var ev in eventSourceEnumerator.Events)
{
    Console.WriteLine(ev.Key); // Event Source name
    foreach (var e in ev.Value)
    {
        // All events for the event source
        Console.WriteLine($"  Id: {e.Key}, Name: {e.Value.Name}, Level: {e.Value.Level}, Payload: {string.Join(",", e.Value.PayloadNames)}");
    }
}

console-showing-etw-events.png?v=e58f

Do you have a question or a suggestion about this post? Contact me!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK