Introduzione
Il logging è spesso il primo strumento diagnostico di ogni applicazione .NET, ma non tutti i logger sono uguali.
In scenari ad alte prestazioni — microservizi, pipeline di messaggi, telemetria distribuita o analisi in tempo reale — l’uso di ILogger tradizionali può introdurre overhead non trascurabili, soprattutto con log voluminosi.
Per questi casi, il runtime .NET offre strumenti nativi a basso livello: EventSource e DiagnosticSource.
Entrambi consentono telemetria efficiente, instrumentation interna e integrazione diretta con sistemi di tracciamento come EventPipe, ETW, OpenTelemetry, o Application Insights — senza sacrificare performance.
EventSource: logging low-level, zero-allocation
Cos’è
EventSource è una classe base in System.Diagnostics.Tracing pensata per scrivere eventi di telemetria in modo ad altissime prestazioni.
Nasce in Windows con ETW (Event Tracing for Windows), ma in .NET Core e successivi è stata estesa anche per Linux/macOS tramite EventPipe.
L’obiettivo:
– emettere eventi strutturati, leggibili da strumenti esterni, senza passare da formattazioni di stringhe o allocazioni di oggetti temporanei.
Esempio base
[EventSource(Name = "SampleApp-Processor")]
public sealed class ProcessorEventSource : EventSource
{
public static readonly ProcessorEventSource Log = new();
[Event(1, Level = EventLevel.Informational)]
public void ProcessingStarted(string jobId)
=> WriteEvent(1, jobId);
[Event(2, Level = EventLevel.Error)]
public void ProcessingFailed(string jobId, string reason)
=> WriteEvent(2, jobId, reason);
}
Uso:
ProcessorEventSource.Log.ProcessingStarted("JOB-423");
try
{
// ... elaborazione ...
}
catch (Exception ex)
{
ProcessorEventSource.Log.ProcessingFailed("JOB-423", ex.Message);
}
Caratteristica chiave: EventSource usa buffer binari a basso overhead, con formattazione differita e supporto nativo in tool come dotnet-trace, PerfView o OpenTelemetry .NET Auto-Instrumentation.
Analisi con EventPipe
Puoi leggere questi eventi in tempo reale con:
dotnet trace collect --process-id 12345
Oppure visualizzarli con strumenti avanzati:
- PerfView (Windows)
- dotnet-trace + dotnet-analyze (cross-platform)
- OpenTelemetry Collector (via exporter EventPipe)
DiagnosticSource: tracing contestuale e propagazione
Mentre EventSource si occupa di log binari performanti, DiagnosticSource fornisce un modo dinamico e contestuale per emettere eventi di tracing che includono payload arbitrari.
È la base di System.Net.Http instrumentation, Entity Framework telemetry, ASP.NET Core Diagnostics, e viene usato internamente da OpenTelemetry .NET SDK.
Esempio pratico
using System.Diagnostics;
var source = new DiagnosticListener("PaymentProcessor");
if (source.IsEnabled("Payment.Started"))
{
source.Write("Payment.Started", new { OrderId = 1001, Amount = 49.90 });
}
// Simulazione logica pagamento
Thread.Sleep(200);
if (source.IsEnabled("Payment.Completed"))
{
source.Write("Payment.Completed", new { OrderId = 1001, DurationMs = 200 });
}
Un listener può intercettare questi eventi in runtime:
DiagnosticListener.AllListeners.Subscribe(listener =>
{
if (listener.Name == "PaymentProcessor")
{
listener.Subscribe(evt =>
{
Console.WriteLine($"Evento: {evt.Key} => {JsonSerializer.Serialize(evt.Value)}");
});
}
});
EventSource vs DiagnosticSource
| Caratteristica | EventSource | DiagnosticSource |
|---|---|---|
| Scopo | Logging binario ad alte prestazioni | Tracing dinamico e contestuale |
| Overhead | Minimo (buffer nativo) | Moderato (JSON/payload) |
| Tipo di evento | Statico, predefinito | Dinamico, runtime |
| Strumenti compatibili | ETW, EventPipe, PerfView | OpenTelemetry, App Insights |
| Uso ideale | High-throughput logging | Tracing applicativo e correlation context |
Best practice: usa EventSource per logging strutturato performante e DiagnosticSource per instrumentation dinamica e propagazione di contesto (trace/span id).
Tracing distribuito con OpenTelemetry
Entrambi gli strumenti si integrano perfettamente con OpenTelemetry:
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("PaymentProcessor", "SampleApp-Processor")
.AddConsoleExporter()
.Build();
AddSource() consente di collegare sia EventSource che DiagnosticSource al pipeline di telemetria unificato.
Il risultato: osservabilità end-to-end, dal tuo codice all’export verso Grafana Tempo, Jaeger o Azure Monitor.
Benchmark e performance
EventSource: overhead di circa 20–30 ns/evento (zero allocazioni).DiagnosticSource: ~300–500 ns/evento, ma con maggiore flessibilità.ILogger: ~1–2 µs/evento (dipende dai formatter e sink).
Su microservizi high-throughput, EventSource può ridurre del 90% il costo di log rispetto a ILogger.
Pattern d’uso consigliati
- Usa EventSource per log interni o metriche ad alta frequenza.
- Espandi DiagnosticSource solo per eventi business/trace distribuiti.
- Integra con OpenTelemetry e
ActivitySourceper correlation ID automatico. - Evita conversioni string-heavy: serializza in binary o JSON lightweight.
- Centralizza i listener in un singleton per ridurre le subscription dinamiche.
EventSource e DiagnosticSource rappresentano due pilastri poco conosciuti ma fondamentali della telemetria .NET moderna.
Usati correttamente, consentono un’osservabilità di livello enterprise con overhead minimo — un passo essenziale per costruire sistemi resilienti, tracciabili e performanti.
In un mondo dove ogni millisecondo conta, imparare a misurare con precisione è il primo passo per ottimizzare davvero.
Qual è la differenza tra DiagnosticSource e ActivitySource?ActivitySource è una specializzazione di DiagnosticSource introdotta con .NET 5, ottimizzata per tracing distribuito compatibile con OpenTelemetry.
Posso combinare ILogger e EventSource?
Sì: molti provider di ILogger (Serilog, ETWLogger, EventPipeLogger) permettono di scrivere verso EventSource mantenendo compatibilità con l’ecosistema Microsoft.Extensions.Logging.
DiagnosticSource è thread-safe?
Sì, l’emissione di eventi è thread-safe, ma i payload devono essere immutabili per garantire coerenza.
Posso usare DiagnosticSource in Blazor o MAUI?
Sì, ma gli strumenti di tracing esterni sono più limitati: consigliato solo per telemetria interna.
Dove trovo gli eventi generati?
dotnet-trace collect- Visual Studio Diagnostic Tools
- OpenTelemetry Collector / Jaeger
- PerfView per Windows
