Condividi tramite


Concetti di tracciamento distribuito .NET

La traccia distribuita è una tecnica di diagnostica che consente ai tecnici di localizzare errori e problemi di prestazioni all'interno delle applicazioni, in particolare quelli che possono essere distribuiti tra più computer o processi. Per informazioni generali su dove è utile il tracciamento distribuito, vedere la panoramica del tracciamento distribuito.

Tracce e attività

Ogni volta che una nuova richiesta viene ricevuta da un'applicazione, può essere associata a una traccia. Nei componenti dell'applicazione scritti in .NET, le unità di lavoro in una traccia sono rappresentate da istanze di System.Diagnostics.Activity e la traccia nel suo complesso costituisce un albero di queste Attività, potenzialmente estendendosi attraverso molti processi distinti. La prima attività creata per una nuova richiesta costituisce la radice dell'albero di traccia e tiene traccia della durata complessiva e dell'esito positivo/negativo della gestione della richiesta. Le attività secondarie possono essere create facoltativamente per dividere il lavoro in passaggi diversi, che possono essere monitorati singolarmente. Ad esempio, data un'attività che tiene traccia di una richiesta HTTP in ingresso specifica in un server web, è possibile creare attività figlie per tenere traccia di ognuna delle query di database necessarie per completare la richiesta. In questo modo è possibile registrare in modo indipendente la durata e l'esito positivo di ogni query. Le attività possono registrare altre informazioni per ogni unità di lavoro, ad esempio OperationName, coppie nome-valore denominate Tagse Events. Il nome identifica il tipo di lavoro eseguito, i tag possono registrare parametri descrittivi del lavoro e gli eventi sono un semplice meccanismo di registrazione per registrare i messaggi di diagnostica con timestamp.

Nota

Un altro nome comune del settore per le unità di lavoro in una traccia distribuita è "Spans". .NET ha adottato il termine "Attività" molti anni fa, prima che il nome "Span" sia stato ben definito per questo concetto.

ID attività

Parent-Child Le relazioni tra le Attività nell'albero di traccia distribuita vengono stabilite utilizzando ID univoci. L'implementazione della distribuzione delle tracce di .NET supporta due schemi ID: lo standard W3C TraceContext, che è l'impostazione predefinita in .NET 5+, e una vecchia convenzione .NET denominata 'Gerarchica' disponibile per retrocompatibilità. Activity.DefaultIdFormat controlla quale schema ID viene usato. Nello standard W3C TraceContext a ogni traccia viene assegnato un ID di traccia a 16 byte univoco globale (Activity.TraceId) e a ogni attività all'interno della traccia viene assegnato un ID span-id univoco a 8 byte (Activity.SpanId). Ogni attività registra l'ID traccia, il relativo span-id e lo span-id del relativo elemento padre (Activity.ParentSpanId). Poiché le tracce distribuite possono tenere traccia del lavoro attraverso i limiti del processo, le attività padre e figlio potrebbero non trovarsi nello stesso processo. La combinazione dell'id di traccia e dello span-id padre può identificare in modo univoco l'attività madre a livello globale, indipendentemente dal processo in cui risiede.

Activity.DefaultIdFormat controlla il formato ID utilizzato per avviare nuove tracce, ma per impostazione predefinita l'aggiunta di una nuova Activity a una traccia esistente utilizza lo stesso formato della Activity padre. Impostare Activity.ForceDefaultIdFormat su true sovrascrive questo comportamento e crea tutte le nuove attività con il DefaultIdFormat, anche quando l'elemento padre utilizza un formato ID diverso.

Avviare e arrestare le attività

Ogni thread in un processo può avere un oggetto Activity corrispondente che tiene traccia del lavoro che si verifica in tale thread, accessibile tramite Activity.Current. L'attività corrente accompagna automaticamente tutte le chiamate sincrone su un unico thread e tiene traccia delle chiamate asincrone elaborate su thread diversi. Se l'attività A è l'attività corrente in un thread e il codice avvia una nuova attività B, B diventa la nuova attività corrente in tale thread. Per impostazione predefinita, l'attività B considera anche l'attività A come padre. Quando l'attività B viene arrestata in un secondo momento, l'attività A verrà ripristinata come attività corrente nel thread. Quando un'attività viene avviata, acquisisce l'ora corrente come Activity.StartTimeUtc. Quando si ferma, Activity.Duration viene calcolata come differenza tra l'ora corrente e l'ora di inizio.

Coordinare oltre i confini dei processi

Per tenere traccia del lavoro attraverso i confini dei processi, gli ID genitore delle attività devono essere trasmessi attraverso la rete in modo che il processo di ricezione possa creare Attività che li riferiscono. Quando si usa il formato W3C TraceContext ID, .NET usa anche le intestazioni HTTP consigliate dal standard per trasmettere queste informazioni. Quando si usa il formato ID Hierarchical, .NET usa un'intestazione HTTP request-id personalizzata per trasmettere l'ID. A differenza di molti altri runtime del linguaggio, le librerie in-box di .NET, ad esempio il server Web ASP.NET e System.Net.Http, comprendono in modo nativo come decodificare e codificare gli ID attività nei messaggi HTTP. Il runtime comprende anche come gestire il flusso dell'ID attraverso chiamate sincrone e asincrone. Ciò significa che le applicazioni .NET che ricevono e generano messaggi HTTP partecipano automaticamente al flusso degli ID di traccia distribuita, senza necessità di scrivere codice speciale da parte dello sviluppatore dell'app o dipendenze dalle librerie di terze parti. Le librerie di terze parti possono aggiungere supporto per la trasmissione di ID su protocolli di messaggi non HTTP o il supporto di convenzioni di codifica personalizzate per HTTP.

Raccogliere tracce

Il codice strumentato può creare oggetti Activity come parte di una traccia distribuita, ma le informazioni in questi oggetti devono essere trasmesse e serializzate in un archivio centralizzato e permanente in modo che l'intera traccia possa essere esaminata utilmente in seguito. Esistono diverse librerie di raccolta di telemetria che possono eseguire questa attività, ad esempio Application Insights, OpenTelemetryo una libreria fornita da un fornitore di dati di telemetria di terze parti o da un fornitore di APM. In alternativa, gli sviluppatori possono creare una raccolta di dati di telemetria dell'attività personalizzata usando System.Diagnostics.ActivityListener o System.Diagnostics.DiagnosticListener. ActivityListener supporta l'osservazione di qualsiasi attività indipendentemente dal fatto che lo sviluppatore abbia conoscenze precedenti su di esso. In questo modo ActivityListener è una soluzione per utilizzo generico semplice e flessibile. Al contrario, l'uso di DiagnosticListener è uno scenario più complesso che richiede che il codice strumentato opti per l'attivazione richiamando DiagnosticSource.StartActivity e che la libreria di raccolta conosca le esatte informazioni di denominazione utilizzate dal codice strumentato durante l'avvio. L'uso di DiagnosticSource e DiagnosticListener consente al creatore e al listener di scambiare oggetti .NET arbitrari e stabilire convenzioni personalizzate di passaggio delle informazioni.

Campionamento

Per migliorare le prestazioni nelle applicazioni ad alta velocità di elaborazione, il tracciamento distribuito su .NET supporta il campionamento di sole alcune tracce anziché registrare tutte le tracce. Per le attività create con l'API di ActivitySource.StartActivity consigliata, le librerie di raccolta di telemetria possono controllare il campionamento con il callback ActivityListener.Sample. La libreria di registrazione può scegliere di non creare affatto l'attività, di crearla con le informazioni minime necessarie per propagare gli ID di traccia distribuita, o di popolarla con informazioni di diagnostica complete. Queste scelte bilanciano l'aumento del sovraccarico delle prestazioni con quello dell'utilità diagnostica. Le attività avviate utilizzando il modello precedente di invocazione di Activity.Activity e DiagnosticSource.StartActivity possono supportare anche il campionamento del DiagnosticListener chiamando prima DiagnosticSource.IsEnabled. Anche quando si acquisisce informazioni di diagnostica complete, l'implementazione di .NET è progettata per essere veloce, associata a un agente di raccolta efficiente, è possibile creare, popolare e trasmettere un'attività in circa un microsecondo su hardware moderno. Il campionamento può ridurre il costo di strumentazione a meno di 100 nanosecondi per ogni attività non registrata.

Passaggi successivi

Per iniziare a usare la traccia distribuita nelle applicazioni .NET, vedere Distributed Tracing Instrumentation.

Per un elenco delle attività emesse in modo nativo da .NET, vedere attività integrate in .NET.