Delen via


Concepten voor gedistribueerde tracering van .NET

Gedistribueerde tracering is een diagnostische techniek waarmee technici fouten en prestatieproblemen in toepassingen kunnen lokaliseren, met name die welke kunnen worden gedistribueerd over meerdere machines of processen. Zie het overzicht van gedistribueerde tracering voor algemene informatie over waar gedistribueerde tracering nuttig is.

Traceringen en activiteiten

Telkens wanneer een nieuwe aanvraag wordt ontvangen door een toepassing, kan deze worden gekoppeld aan een tracering. In toepassingsonderdelen die zijn geschreven in .NET, worden werkeenheden in een trace vertegenwoordigd door exemplaren van System.Diagnostics.Activity en de tracering als geheel vormt een boomstructuur van deze activiteiten, mogelijk verspreid over veel verschillende processen. De eerste activiteit die is gemaakt voor een nieuwe aanvraag vormt de hoofdmap van de traceringsstructuur en houdt de totale duur en geslaagde/mislukte verwerking van de aanvraag bij. Onderliggende activiteiten kunnen eventueel worden gemaakt om het werk onder te verdelen in verschillende stappen die afzonderlijk kunnen worden bijgehouden. Bijvoorbeeld, op basis van een activiteit die een specifieke binnenkomende HTTP-aanvraag in een webserver heeft bijgehouden, kunnen onderliggende activiteiten worden gemaakt om elk van de databasequery's bij te houden die nodig waren om de aanvraag te voltooien. Hierdoor kan de duur en het succes van elke query onafhankelijk worden vastgelegd. Activiteiten kunnen andere gegevens vastleggen voor elke werkeenheid, zoals OperationNamenaam-waardeparen die worden aangeroepen Tagsen Events. De naam identificeert het type werk dat wordt uitgevoerd, tags kunnen beschrijvende parameters van het werk vastleggen en gebeurtenissen zijn een eenvoudig mechanisme voor logboekregistratie om tijdgebonden diagnostische berichten vast te leggen.

Notitie

Een andere algemene branchenaam voor werkeenheden in een gedistribueerde tracering zijn 'Spans'. .NET heeft de term 'Activiteit' vele jaren geleden aangenomen, voordat de naam 'Span' goed tot stand is gebracht voor dit concept.

Activiteit-id's

Bovenliggende/onderliggende relaties tussen activiteiten in de gedistribueerde traceringsstructuur worden tot stand gebracht met behulp van unieke id's. . De implementatie van gedistribueerde tracering van NET ondersteunt twee id-schema's: de W3C-standaard TraceContext, de standaardinstelling in .NET 5+ en een oudere .NET-conventie genaamd 'Hierarchical' die beschikbaar is voor compatibiliteit met eerdere versies. Activity.DefaultIdFormat bepaalt welk id-schema wordt gebruikt. In de W3C TraceContext-standaard wordt aan elke trace een wereldwijd unieke tracerings-id van 16 byte (Activity.TraceId) toegewezen, en aan elke activiteit binnen de trace wordt een unieke span-id van 8 bytes (Activity.SpanId) toegewezen. Elke activiteit registreert de trace-id, de eigen span-id en de span-id van de bovenliggende id (Activity.ParentSpanId). Omdat gedistribueerde traceringen werk kunnen bijhouden over procesgrenzen, bevinden bovenliggende en onderliggende activiteiten zich mogelijk niet in hetzelfde proces. De combinatie van een trace-id en bovenliggende span-id kan de bovenliggende activiteit wereldwijd uniek identificeren, ongeacht het proces waarin deze zich bevindt.

Activity.DefaultIdFormat bepaalt welke id-indeling wordt gebruikt voor het starten van nieuwe traceringen, maar het toevoegen van een nieuwe activiteit aan een bestaande tracering maakt gebruik van de indeling die de bovenliggende activiteit gebruikt. Als deze instelling is ingesteld Activity.ForceDefaultIdFormat op true, wordt dit gedrag overschreven en worden alle nieuwe activiteiten gemaakt met de DefaultIdFormat, zelfs wanneer het bovenliggende item een andere id-indeling gebruikt.

Activiteiten starten en stoppen

Elke thread in een proces kan een bijbehorend activiteitsobject hebben waarmee het werk op die thread wordt bijgehouden, toegankelijk via Activity.Current. De huidige activiteit loopt automatisch door alle synchrone aanroepen op een thread en volgt asynchrone aanroepen die op verschillende threads worden verwerkt. Als Activiteit A de huidige activiteit op een thread is en code een nieuwe activiteit B start, wordt B de nieuwe huidige activiteit op die thread. Standaard behandelt activiteit B activiteit A ook als de bovenliggende activiteit. Wanneer activiteit B later wordt gestopt, wordt activiteit A hersteld als de huidige activiteit op de thread. Wanneer een activiteit wordt gestart, wordt de huidige tijd vastgelegd als de Activity.StartTimeUtc. Wanneer deze stopt, Activity.Duration wordt dit berekend als het verschil tussen de huidige tijd en de begintijd.

Coördinaat over procesgrenzen

Om werk over procesgrenzen bij te houden, moeten bovenliggende id's van activiteit via het netwerk worden verzonden, zodat het ontvangende proces activiteiten kan maken die ernaar verwijzen. Wanneer u de W3C TraceContext ID-indeling gebruikt, gebruikt .NET ook de HTTP-headers die door de standaard worden aanbevolen om deze informatie te verzenden. Wanneer u de Hierarchical id-indeling gebruikt, gebruikt .NET een aangepaste HTTP-header voor aanvraag-id om de id te verzenden. In tegenstelling tot veel andere taalruntimes begrijpen .NET-in-box-bibliotheken zoals de ASP.NET webserver en System.Net.Http systeemeigen inzicht in het decoderen en coderen van activiteits-id's op HTTP-berichten. De runtime begrijpt ook hoe de id wordt gestroomd via synchrone en asynchrone aanroepen. Dit betekent dat .NET-toepassingen die HTTP-berichten ontvangen en verzenden, automatisch deelnemen aan gedistribueerde tracerings-id's, zonder speciale codering door de app-ontwikkelaar of bibliotheekafhankelijkheden van derden. Bibliotheken van derden kunnen ondersteuning toevoegen voor het verzenden van id's via niet-HTTP-berichtprotocollen of het ondersteunen van aangepaste coderingsconventies voor HTTP.

Traceringen verzamelen

Instrumented code kan objecten maken Activity als onderdeel van een gedistribueerde trace, maar de informatie in deze objecten moet worden verzonden en geserialiseerd in een gecentraliseerd permanent archief, zodat de volledige tracering later nuttig kan worden beoordeeld. Er zijn verschillende telemetrieverzamelingsbibliotheken die deze taak kunnen uitvoeren, zoals Application Insights, OpenTelemetry of een bibliotheek die wordt geleverd door een externe telemetrie of APM-leverancier. Ontwikkelaars kunnen ook hun eigen aangepaste telemetrieverzameling voor activiteit maken met behulp van System.Diagnostics.ActivityListener of System.Diagnostics.DiagnosticListener. ActivityListener biedt ondersteuning voor het observeren van activiteiten, ongeacht of de ontwikkelaar over deze activiteit beschikt. Hierdoor is ActivityListener een eenvoudige en flexibele oplossing voor algemeen gebruik. Het gebruik van DiagnosticListener is daarentegen een complexer scenario dat vereist dat de geïnstrueerde code zich aanmeldt door aan te DiagnosticSource.StartActivity roepen en de verzamelingsbibliotheek de exacte naamgevingsgegevens moet kennen die door de geïnstrueerde code worden gebruikt bij het starten ervan. Met behulp van DiagnosticSource en DiagnosticListener kunnen de maker en listener willekeurige .NET-objecten uitwisselen en aangepaste conventies voor het doorgeven van gegevens tot stand brengen.

Steekproeven

Voor verbeterde prestaties in toepassingen met hoge doorvoer ondersteunt gedistribueerde tracering op .NET alleen steekproeven in een subset van traceringen in plaats van ze allemaal op te nemen. Voor activiteiten die zijn gemaakt met de aanbevolen ActivitySource.StartActivity API, kunnen telemetrieverzamelingsbibliotheken steekproeven beheren met de ActivityListener.Sample callback. De logboekregistratiebibliotheek kan ervoor kiezen om de activiteit helemaal niet te maken, om deze te maken met minimale informatie die nodig is om tracerings-id's door te geven of om deze te vullen met volledige diagnostische gegevens. Deze keuzes maken een afweging tussen het verhogen van de prestatieoverhead voor het verhogen van het diagnostische hulpprogramma. Activiteiten die worden gestart met het oudere patroon van aanroepen Activity.Activity en DiagnosticSource.StartActivity kunnen ook diagnosticListener-steekproeven ondersteunen door eerst aan te roepen DiagnosticSource.IsEnabled. Zelfs bij het vastleggen van volledige diagnostische gegevens is de .NET-implementatie ontworpen om snel te zijn, in combinatie met een efficiënte collector, kan een activiteit worden gemaakt, gevuld en verzonden in ongeveer een microseconde op moderne hardware. Steekproeven kunnen de instrumentatiekosten verlagen tot minder dan 100 nanoseconden voor elke activiteit die niet is vastgelegd.

Volgende stappen

Zie de Distributed Tracing Instrumentation voor gedistribueerde tracering om aan de slag te gaan met gedistribueerde tracering in .NET-toepassingen.