Condividi tramite


Tracciamento distribuito nelle librerie di System.Net

Tracciamento distribuito è una tecnica diagnostica che consente agli ingegneri di localizzare guasti e problemi di prestazioni all'interno delle applicazioni, in particolare quelli distribuiti tra più computer o processi. Questa tecnica tiene traccia delle richieste tramite un'applicazione correlando il lavoro svolto da componenti diversi e separandolo da altre operazioni che l'applicazione potrebbe eseguire per le richieste simultanee. Ad esempio, una richiesta a un servizio Web tipico potrebbe essere ricevuta prima da un servizio di bilanciamento del carico e quindi inoltrata a un processo del server Web, che esegue quindi diverse query a un database. La traccia distribuita consente ai tecnici di distinguere se uno di questi passaggi non è riuscito e il tempo necessario per ogni passaggio. Può anche registrare i messaggi generati da ogni passaggio durante l'esecuzione.

Il sistema di traccia in .NET è progettato per funzionare con OpenTelemetry (OTel) e usa OTel per esportare i dati nei sistemi di monitoraggio. Il tracciamento in .NET viene implementato usando le API di System.Diagnostics, in cui un'unità di lavoro è rappresentata dalla classe System.Diagnostics.Activity, che corrisponde a una traccia dell'intervallo OTel. OpenTelemetry definisce uno schema di denominazione standard a livello di settore per intervalli (attività) insieme ai relativi attributi (tag), noti come convenzioni semantiche . I dati di telemetria .NET usano convenzioni semantiche esistenti laddove possibile.

Nota

I termini e attività sono sinonimi in questo articolo. Nel contesto del codice .NET, fanno riferimento a un'istanza di System.Diagnostics.Activity. Non confondere l'intervallo OTel con System.Span<T>.

Mancia

Per un elenco completo di tutte le attività predefinite insieme ai relativi tag/attributi, vedere attività predefinite in .NET.

Strumentazione

Per generare tracce, le librerie di System.Net vengono instrumentate con origini ActivitySource predefinite, che creano oggetti Activity per tenere traccia del lavoro eseguito. Le attività vengono create solo se sono presenti ascoltatori iscritti al ActivitySource.

La strumentazione predefinita si è evoluta con le versioni di .NET.

  • In .NET 8 e versioni precedenti, la strumentazione è limitata alla creazione di un'attività di richiesta client HTTP vuota . Ciò significa che gli utenti devono basarsi sulla libreria OpenTelemetry.Instrumentation.Http per popolare l'attività con le informazioni (ad esempio, tag) necessarie per generare tracce utili.
  • .NET 9 ha esteso la strumentazione emettendo il nome, lo stato, le informazioni sulle eccezioni e i tag più importanti secondo le convenzioni semantiche OTel per il client HTTP nell'attività di richiesta del client HTTP. Ciò significa che in .NET 9+, la dipendenza OpenTelemetry.Instrumentation.Http può essere omessa, a meno che non siano necessarie funzionalità più avanzate come arricchimento.
  • .NET 9 ha anche introdotto tracce di connessione sperimentali, aggiungendo nuove attività nelle librerie System.Net per supportare la diagnosi dei problemi di connessione.

Raccogliere tracce di System.Net

Al livello più basso, la raccolta di tracce è supportata tramite il metodo AddActivityListener, che registra ActivityListener oggetti contenenti la logica definita dall'utente.

Tuttavia, in qualità di sviluppatore di applicazioni, è probabile che si preferisca basarsi sull'ecosistema avanzato basato sulle funzionalità fornite dal OpenTelemetry .NET SDK per raccogliere, esportare e monitorare le tracce.

Raccogliere tracce con .NET Aspirare

Un modo semplice per raccogliere tracce e metriche nelle applicazioni ASP.NET consiste nell'usare .NET Aspire. .NET Aspire è un set di estensioni per .NET per semplificare la creazione e l'uso di applicazioni distribuite. Uno dei vantaggi dell'uso di .NET Aspire è che i dati di telemetria sono incorporati, usando le librerie OpenTelemetry per .NET.

I modelli di progetto predefiniti per .NET Aspire contengono un progetto ServiceDefaults. Ogni servizio nella soluzione .NET Aspire ha un riferimento al progetto Service Defaults. I servizi lo usano per impostare e configurare OTel.

Il modello di progetto Service Defaults include i pacchetti OTel SDK, ASP.NET, HttpClient e strumentazione del runtime. Questi componenti di strumentazione vengono configurati nel file Extensions.cs. Per supportare la visualizzazione dei dati di telemetria in Aspira dashboard, il progetto Service Defaults include anche l'utilità di esportazione OTLP per impostazione predefinita.

Aspira dashboard è progettato per portare l'osservazione dei dati di telemetria al ciclo di debug locale, che consente agli sviluppatori di garantire che le applicazioni producano dati di telemetria. La visualizzazione dei dati di telemetria consente anche di diagnosticare tali applicazioni in locale. La possibilità di osservare le chiamate tra i servizi è utile in fase di debug, come nell'ambiente di produzione. Il dashboard .NET Aspire viene avviato automaticamente quando si F5 il progetto AppHost da Visual Studio o dotnet run il progetto AppHost dalla riga di comando.

Aspira dashboard

Per altre informazioni su .NET Aspire, vedere:

Riutilizzare il progetto Service Defaults senza .NET Aspire Orchestration

Il progetto Aspire Service Defaults offre un modo semplice per configurare OTel per i progetti ASP.NET, anche senza usare il restante di .NET Aspire come AppHost per l'orchestrazione. Il progetto Service Defaults è disponibile come modello di progetto tramite Visual Studio o dotnet new. Imposta OTel e configura l'esportatore OTLP. È quindi possibile usare le variabili di ambiente OTel per configurare l'endpoint OTLP per inviare dati di telemetria e fornire le proprietà delle risorse per l'applicazione.

I passaggi per usare ServiceDefaults all'esterno di .NET Aspire sono:

  1. Aggiungere il progetto ServiceDefaults alla soluzione usando Aggiungi nuovo progetto in Visual Studio oppure usare dotnet new:

    dotnet new aspire-servicedefaults --output ServiceDefaults
    
  2. Fare riferimento al progetto ServiceDefaults dalla tua applicazione ASP.NET. In Visual Studio selezionare Aggiungi>Riferimento al Progetto e selezionare il progetto ServiceDefaults

  3. Chiamare la funzione di installazione di OpenTelemetry ConfigureOpenTelemetry() come parte dell'inizializzazione del generatore di applicazioni.

    var builder = WebApplication.CreateBuilder(args)
    builder.ConfigureOpenTelemetry(); // Extension method from ServiceDefaults.
    var app = builder.Build();
    app.MapGet("/", () => "Hello World!");
    app.Run();
    

Per una procedura dettagliata completa, vedere Esempio: Usare OpenTelemetry con OTLP e l'Aspire Dashboard autonomo.

Tracciamento sperimentale della connessione

Durante la risoluzione dei problemi HttpClient o dei colli di bottiglia, potrebbe essere fondamentale capire dove viene impiegato il tempo nell'invio di richieste HTTP. Spesso, il problema si verifica durante la definizione della connessione HTTP, che in genere si suddivide in ricerca DNS, connessione TCP e handshake TLS.

.NET 9 ha introdotto il tracciamento sperimentale delle connessioni aggiungendo uno span HTTP connection setup con tre span figlio che rappresentano le fasi DNS, TCP e TLS della connessione. La parte HTTP della traccia di connessione viene implementata all'interno di SocketsHttpHandler, ovvero il modello di attività deve rispettare il comportamento del pool di connessioni sottostante.

Nota

In SocketsHttpHandlerle connessioni e le richieste hanno cicli di vita indipendenti. Una connessione in pool può essere attiva per molto tempo e gestire molte richieste. Quando si effettua una richiesta, se non è disponibile alcuna connessione immediatamente nel pool di connessioni, la richiesta viene aggiunta a una coda di richieste per attendere una connessione disponibile. Non esiste alcuna relazione diretta tra le richieste in attesa e le connessioni. Il processo di connessione potrebbe essere stato avviato quando un'altra connessione è diventata disponibile per l'uso, nel qual caso viene usata la connessione liberata. Di conseguenza, l'intervallo di HTTP connection setup non viene modellato come figlio dell'intervallo di HTTP client request; Vengono invece usati i collegamenti span.

.NET 9 ha introdotto gli intervalli seguenti per consentire la raccolta di informazioni dettagliate sulla connessione:

Nome ActivitySource Descrizione
HTTP wait_for_connection Experimental.System.Net.Http.Connections Intervallo figlio dell'intervallo di HTTP client request che rappresenta l'intervallo di tempo in cui la richiesta è in attesa di una connessione disponibile nella coda delle richieste.
HTTP connection_setup Experimental.System.Net.Http.Connections Rappresenta l'istituzione della connessione HTTP. Intervallo radice di traccia separato con il proprio TraceId. Gli HTTP client request segmenti possono contenere collegamenti a HTTP connection_setup.
DNS lookup Experimental.System.Net.NameResolution Ricerca DNS eseguita dalla classe Dns.
socket connect Experimental.System.Net.Sockets Creazione di una connessione Socket.
TLS handshake Experimental.System.Net.Security L'handshake del client o del server TLS eseguito da SslStream.

Nota

I nomi di ActivitySource corrispondenti iniziano con il prefisso Experimental, poiché questi intervalli potrebbero essere modificati nelle versioni future, man mano che si apprenderà come funzionano correttamente nell'ambiente di produzione.

Questi intervalli sono troppo verbosi per un uso continuo negli scenari di produzione con carichi di lavoro elevati, essendo difficili da gestire, e questo livello di strumentazione non è normalmente necessario. Tuttavia, se si sta tentando di diagnosticare i problemi di connessione o ottenere una comprensione più approfondita del modo in cui la latenza di rete e connessione influisce sui servizi, forniscono informazioni dettagliate difficili da raccogliere con altri mezzi.

Quando la Experimental.System.Net.Http.Connections ActivitySource è abilitata, l'intervallo di HTTP client request contiene un collegamento all'intervallo di HTTP connection_setup corrispondente alla connessione che gestisce la richiesta. Poiché una connessione HTTP può essere di lunga durata, ciò potrebbe comportare molti collegamenti all'intervallo di connessione da ognuna delle attività della richiesta. Alcuni strumenti di monitoraggio APM navigano in modo aggressivo i collegamenti tra gli intervalli per creare le loro visualizzazioni e, di conseguenza, includere questo span può causare problemi se gli strumenti non sono stati progettati per gestire un numero elevato di collegamenti.

Il diagramma seguente illustra il comportamento degli intervalli e la relativa relazione:

la connessione si estende nel tempo.

Procedura dettagliata: Uso della traccia di connessione sperimentale in .NET 9

Questa procedura dettagliata usa un .NET 9 Aspire Starter App per illustrare la traccia delle connessioni, ma dovrebbe essere facile configurarla con anche altri strumenti di monitoraggio. Il passaggio chiave consiste nell'abilitare ActivitySources.

  1. Creare un'app .NET Aspire 9 Starter usando dotnet new:

    dotnet new aspire-starter-9 --output ConnectionTracingDemo
    

    In alternativa, in Visual Studio:

    Creare un'applicazione iniziale .NET Aspire 9 in Visual Studio

  2. Aprire Extensions.cs nel progetto di ServiceDefaults e modificare il metodo ConfigureOpenTelemetry aggiungendo ActivitySources per la connessione nel callback di configurazione della traccia:

    .WithTracing(tracing =>
    {
        tracing.AddAspNetCoreInstrumentation()
            // Instead of using .AddHttpClientInstrumentation()
            // .NET 9 allows to add the ActivitySources directly.
            .AddSource("System.Net.Http")
            // Add the experimental connection tracking ActivitySources using a wildcard.
            .AddSource("Experimental.System.Net.*");
    });
    
  3. Avviare la soluzione. Dovrebbe aprire il .NET Aspire Dashboard.

  4. Vai alla pagina Meteo dell'app webfrontend per generare una richiesta HttpClient verso apiservice.

  5. Tornare al Dashboard e navigare alla pagina Traces. Aprire la traccia webfrontend: GET /weather.

    Tracciamenti HttpClient nel Dashboard di Aspire

Quando le richieste HTTP vengono effettuate con la strumentazione della connessione abilitata, verranno visualizzate le modifiche seguenti all'intervallo di richieste client:

  • Se deve essere stabilita una connessione o se l'app è in attesa di una connessione dal pool di connessioni, viene visualizzato un intervallo di HTTP wait_for_connection aggiuntivo che rappresenta il ritardo di attesa di una connessione. Ciò consente di comprendere i ritardi tra la richiesta HttpClient effettuata nel codice e l'avvio effettivo dell'elaborazione della richiesta. Nell'immagine precedente:
    • L'intervallo selezionato è la richiesta HttpClient.
    • L'intervallo seguente rappresenta il tempo che la richiesta trascorre in attesa che una connessione venga stabilita.
    • L'ultimo intervallo in giallo proviene dalla destinazione che elabora la richiesta.
  • L'intervallo HttpClient avrà un collegamento all'intervallo di HTTP connection_setup, che rappresenta l'attività per creare la connessione HTTP usata dalla richiesta.

configurazione della connessione in Aspire Dashboard si estende in

Come accennato in precedenza, l'intervallo di HTTP connection_setup è un intervallo separato con il proprio TraceId, poiché la durata è indipendente da ogni singola richiesta client. Questo intervallo ha solitamente intervalli figlio DNS lookup, (TCP) socket connect, e TLS client handshake.

Arricchimento

In alcuni casi, è necessario aumentare la funzionalità di traccia System.Net esistente. In genere questo significa inserire tag/attributi aggiuntivi per le attività predefinite. Questo metodo viene chiamato arricchimento .

API di arricchimento nella libreria di strumentazione OpenTelemetry

Per aggiungere altri tag/attributi all'attività di richiesta client HTTP, l'approccio più semplice consiste nell'usare le API di arricchimento HttpClient della libreria di strumentazione HttpClient e HttpWebRequest di OpenTelemetry. Ciò richiede di avere una dipendenza dal pacchetto OpenTelemetry.Instrumentation.Http.

Arricchimento manuale

L'arricchimento dell'attività HTTP client request può essere implementato manualmente. Per questo è necessario accedere Activity.Current nel codice in esecuzione nell'ambito dell'attività della richiesta, prima che l'attività venga completata. A tale scopo, è possibile implementare un IObserver<DiagnosticListener> e sottoscriverlo a AllListeners per ottenere i callback per quando si verifica un'attività di rete. Infatti, questo è il modo in cui viene implementata la libreria di strumentazione OpenTelemetry HttpClient e HttpWebRequest. Per un esempio di codice, vedere il codice di sottoscrizione in DiagnosticSourceSubscriber.cs e l'implementazione sottostante in HttpHandlerDiagnosticListener.cs a cui vengono delegate le notifiche.

Sono necessarie altre tracce?

Se hai suggerimenti per altre informazioni utili che potrebbero essere esposte tramite tracciamento, segnala un problema dotnet/runtime.