Course contentsShow
← C#
Lesson 1754 of 1,90816. Performance and DiagnosticsFree lesson

Implementing Custom Diagnostic Source Listeners

Students will hook into runtime diagnostic events to monitor system behavior in real-time.

In this lesson, you will learn how to intercept and process real-time runtime events by implementing custom DiagnosticListener observers.

Beyond Standard Counters

While EventCounters are excellent for aggregate metrics like "requests per second," sometimes you need granular, event-based telemetry—such as tracking the lifecycle of a specific database query or identifying when a long-running background task starts and stops. DiagnosticSource provides a decoupled way for libraries to publish these events without knowing who, if anyone, is listening.

Implementing the Observer

To capture these events, you must implement IObserver<DiagnosticListener>. Your observer acts as a "filter" that decides which specific diagnostic sources you care about (e.g., Microsoft.AspNetCore). Once you identify a source of interest, you subscribe to it using an IObserver<KeyValuePair<string, object>>.

Here is a simplified pattern for hooking into these events:

public class MyDiagnosticObserver : IObserver<DiagnosticListener>
{
    public void OnNext(DiagnosticListener listener)
    {
        // Filter for specific sources (e.g., Entity Framework or custom ones)
        if (listener.Name == "MyCustomSource")
        {
            listener.Subscribe(new MyEventObserver());
        }
    }

    public void OnCompleted() { }
    public void OnError(Exception error) { }
}

public class MyEventObserver : IObserver<KeyValuePair<string, object>>
{
    public void OnNext(KeyValuePair<string, object> value)
    {
        // Extract the event name and the payload (the object)
        Console.WriteLine($"Event: {value.Key}");
    }

    public void OnCompleted() { }
    public void OnError(Exception error) { }
}

Hooking it Up

To start receiving events, you must globally register your listener with the DiagnosticListener.AllListeners observable:

DiagnosticListener.AllListeners.Subscribe(new MyDiagnosticObserver());

Why this matters

Because DiagnosticSource is designed for performance, the overhead is minimal when no one is listening. By implementing a custom listener, you gain deep visibility into the "inner heartbeat" of your application. You can extract payload objects from these events to log specific metadata, calculate exact durations, or trigger alerts based on complex state transitions that traditional metrics cannot express.

Key Takeaway: Custom Diagnostic Listeners allow you to decouple high-frequency internal application events from your logging logic, providing a low-overhead path for real-time observability into your system's critical execution paths.