Concepts de suivi distribué .NET
Le suivi distribué est une technique de diagnostic qui aide les ingénieurs à localiser les défaillances et les problèmes de performances au sein des applications, en particulier ceux qui peuvent être distribués sur plusieurs ordinateurs ou processus. Consultez la Vue d’ensemble du suivi distribué pour obtenir des informations générales sur l’endroit où le suivi distribué est utile.
Traces et activités
Chaque fois qu’une nouvelle demande est reçue par une application, elle peut être associée à une trace. Dans les composants d’application écrits dans .NET, les unités de travail d’une trace sont représentées par des instances de System.Diagnostics.Activity et la trace dans son ensemble forme une arborescence de ces activités, pouvant s’étaler sur de nombreux processus distincts. La première activité créée pour une nouvelle demande forme la racine de l’arborescence de trace et suit la durée globale et la réussite/échec de la demande. Les activités enfants peuvent éventuellement être créées pour subdiviser le travail en différentes étapes qui peuvent être suivies individuellement. Si l’on prend l’exemple d’une activité qui suivait une requête HTTP entrante spécifique dans un serveur web, les activités enfants pourraient être créées pour suivre chacune des requêtes de base de données nécessaires pour terminer la demande. Cela permet d’enregistrer la durée et la réussite de chaque requête indépendamment. Les activités peuvent enregistrer d’autres informations pour chaque unité de travail, telles que OperationName, les paires nom-valeur appelées Tagset Events. Le nom identifie le type de travail en cours d’exécution, les balises peuvent enregistrer des paramètres descriptifs du travail, et les événements sont un mécanisme de journalisation simple pour enregistrer les messages de diagnostic horodatés.
Remarque
Dans le secteur, un autre nom commun pour les unités de travail dans une trace distribuée sont les « étendues ». .NET a adopté le terme « Activité » il y a de nombreuses années, avant que le nom « Span » soit bien établi pour ce concept.
ID d’activité
Parent-Child Les relations entre les activités de l'arborescence de trace distribuée sont établies à l'aide d'IDs uniques. L’implémentation du suivi distribué de .NET prend en charge deux schémas d’ID : le standard W3C TraceContext, qui est la valeur par défaut dans .NET 5+, et une convention .NET plus ancienne appelée « Hiérarchique » disponible pour la compatibilité ascendante. Activity.DefaultIdFormat contrôle le schéma d’ID utilisé. Dans la norme W3C TraceContext, chaque trace est affectée à un ID de trace de 16 octets (Activity.TraceId) globalement unique, et chaque activité au sein de la trace reçoit un id d’étendue de 8 octets unique (Activity.SpanId). Chaque activité enregistre l’ID de trace, son propre ID d’étendue et l’ID d’étendue de son parent (Activity.ParentSpanId). Étant donné que les traces distribuées peuvent suivre le travail entre les limites de processus, les activités parent et enfant peuvent ne pas se trouver dans le même processus. La combinaison d’un ID de trace et d’un ID d’étendue parent peut identifier de manière unique l’activité parente globalement, quel que soit le processus dans lequel elle réside.
Activity.DefaultIdFormat contrôle le format d’ID utilisé pour démarrer de nouvelles traces, mais par défaut, l’ajout d’une nouvelle activité à une trace existante utilise le format utilisé par l’activité parente. Définir Activity.ForceDefaultIdFormat sur true remplace ce comportement et crée toutes les nouvelles activités avec DefaultIdFormat, même lorsque le parent utilise un autre format d’ID.
Démarrer et arrêter les activités
Chaque thread d’un processus peut avoir un objet d’activité correspondant qui suit le travail sur ce thread, accessible via Activity.Current. L’activité actuelle circule automatiquement le long de tous les appels synchrones sur un thread et suit les appels asynchrones traités sur différents threads. Si l’activité A est l’activité actuelle sur un thread et que le code démarre une nouvelle activité B, B devient la nouvelle activité actuelle sur ce thread. Par défaut, l’activité B traite également l’activité A comme son parent. Lorsque l’activité B est arrêtée ultérieurement, l’activité A est restaurée en tant qu’activité active sur le thread. Quand une activité est démarrée, elle capture l’heure actuelle en tant que Activity.StartTimeUtc. Lorsqu’il s’arrête, Activity.Duration est calculé comme la différence entre l’heure actuelle et l’heure de début.
Coordonner au-delà des limites de processus
Pour suivre le travail au-delà des limites de processus, les ID parents d’activité doivent être transmis sur le réseau afin que le processus récepteur puisse créer des activités qui s'y réfèrent. Lorsque vous utilisez le format d’ID TraceContext W3C, .NET utilise également les en-têtes HTTP recommandés par le standard pour transmettre ces informations. Lorsque vous utilisez le format d’ID Hierarchical, .NET utilise un en-tête HTTP request-id personnalisé pour transmettre l’ID. Contrairement à de nombreux autres runtimes de langage, les bibliothèques .NET in-box telles que le serveur web ASP.NET et System.Net.Http en mode natif comprennent comment décoder et encoder des ID d’activité sur les messages HTTP. Le runtime comprend également comment transmettre l’ID via des appels synchrones et asynchrones. Cela signifie que les applications .NET qui reçoivent et émettent des messages HTTP participent automatiquement aux ID de trace distribués transmis, sans codage spécial par le développeur de l’application ou les dépendances de bibliothèque tierce. Les bibliothèques tierces peuvent ajouter la prise en charge de la transmission d’ID sur des protocoles de messages non HTTP ou prendre en charge des conventions d’encodage personnalisées pour HTTP.
Collecter des traces
Le code instrumenté peut créer des objets Activity dans le cadre d’une trace distribuée, mais les informations contenues dans ces objets doivent être transmises et sérialisées dans un magasin persistant centralisé afin que la trace entière puisse être examinée plus tard. Il existe plusieurs bibliothèques de collecte de données de télémétrie qui peuvent effectuer cette tâche, telles que Application Insights, OpenTelemetry, ou une bibliothèque fournie par un fournisseur de télémétrie tiers ou APM. Les développeurs peuvent également créer leur propre collection de données de télémétrie d’activité personnalisée à l’aide de System.Diagnostics.ActivityListener ou de System.Diagnostics.DiagnosticListener. ActivityListener prend en charge l’observation de n’importe quelle activité, que le développeur ait des connaissances préalables sur celle-ci. Cela rend ActivityListener une solution simple et flexible à usage général. En revanche, l’utilisation de DiagnosticListener est un scénario plus complexe qui exige que le code instrumenté s’inscrive en appelant DiagnosticSource.StartActivity, et la bibliothèque de collecte doit connaître les informations de nom exactes utilisées par le code instrumenté lors de son démarrage. L’utilisation de DiagnosticSource et de DiagnosticListener permet au créateur et à l’écouteur d’échanger des objets .NET arbitraires et d’établir des conventions de passage d’informations personnalisées.
Échantillonnage
Pour améliorer les performances dans les applications à débit élevé, le suivi distribué sur .NET prend en charge l’échantillonnage uniquement d’un sous-ensemble de traces plutôt que d’en enregistrer tous. Pour les activités créées avec l'API recommandée ActivitySource.StartActivity, les bibliothèques de collecte de télémétrie peuvent contrôler l'échantillonnage avec la fonction de rappel ActivityListener.Sample. La bibliothèque de journalisation peut choisir de ne pas créer l’activité du tout, de la créer avec des informations minimales nécessaires pour propager la distribution des ID de suivi ou pour la remplir avec des informations de diagnostic complètes. Ces choix remplacent l’augmentation de la surcharge des performances pour l’augmentation de l’utilité de diagnostic. Les activités qui ont commencé à utiliser l’ancien modèle d’appel de Activity.Activity et DiagnosticSource.StartActivity peuvent également prendre en charge l’échantillonnage DiagnosticListener en appelant d’abord DiagnosticSource.IsEnabled. Même lors de la capture d’informations de diagnostic complètes, l’implémentation .NET est conçue pour être rapide , couplée à un collecteur efficace, une activité peut être créée, remplie et transmise dans environ une microseconde sur le matériel moderne. L’échantillonnage peut réduire le coût d’instrumentation à moins de 100 nanosecondes pour chaque activité qui n’est pas enregistrée.
Étapes suivantes
Pour obtenir un exemple de code permettant de commencer à utiliser le suivi distribué dans les applications .NET, consultez la Distributed Tracing Instrumentation.
Pour obtenir la liste des activités émises en mode natif par .NET, consultez activités intégrées dans .NET.