Språk

Konfigurera distribuerad spårning i .NET

I .NET 11 och senare låter API:erna Microsoft.Extensions.Diagnostics.Tracing dig registrera ActivityListener instanser och använda regler för att välja de ActivitySource instanser och Activity som varje lyssnare tar emot. Definiera regler i kod eller läs in dem från IConfiguration.

Important

Spårningsregler påverkar endast lyssnare som registrerats via den här spårningsinfrastrukturen. De påverkar inte orelaterade ActivityListener instanser, inklusive lyssnare som telemetriexportörer skapar och hanterar. Konfigurera lyssnarna eller exportörerna separat.

Registrera spårning

API:erna är tillgängliga i Microsoft.Extensions.Diagnostics paketet. Appar som refererar till det delade ramverket Microsoft.AspNetCore.App innehåller redan sammansättningen.

Anropa AddTracing på en IServiceCollection. I återanropet:

  • Ring AddListener för att registrera varje lyssnare. Lyssnarnamnet identifierar lyssnaren i konfigurationsregler.
  • Konfigurera lyssnarens sampling och meddelandedelegater via ActivityListenerBuilder. Spårningsinfrastrukturen äger ShouldListenTo, källprenumerationer och lyssnarens livslängd.
  • Anropa AddConfiguration med konfigurationsavsnittet som innehåller reglerna. För ett avsnitt med namnet Tracing, skicka configuration.GetSection("Tracing").

Det fullständiga exemplet visar alla tre anropen. En .NET värd aktiverar spårningsprenumerationer när värden startar. Om du använder beroendeinmatning utan värd kan du lösa det registrerade ActivitySourceFactory för att konstruera lyssnarna och aktivera deras prenumerationer. Det fullständiga exemplet löser fabriken direkt.

Konfigurera spårning

Ange spårningsregler via konfiguration eller kod. Om ingen regel matchar en lyssnare, källa, åtgärd och omfång förblir spårning inaktiverad för den kombinationen.

Konfigurera spårning utan kod

För appar som använder konfiguration lägger du till ett Tracing avsnitt iappsettings.json eller någon annan konfigurationsprovider. Skicka sedan avsnittet till AddConfiguration:

tracing.AddConfiguration(configuration.GetSection("Tracing"));

I följande exempel visas de regelavsnitt och regelnivåer som stöds:

{
  "Tracing": {
    "EnabledTracing": {
      "Default": false,
      "Contoso": true,
      "Contoso.Orders": {
        "Default": true,
        "HealthCheck": false
      },
      "Contoso.*.Storage": true
    },
    "EnabledGlobalTracing": {
      "System.Net.Http": true
    },
    "EnabledLocalTracing": {
      "Contoso.Workers": true
    },
    "Console": {
      "EnabledLocalTracing": {
        "Contoso.Orders": {
          "Submit": false
        }
      }
    }
  }
}

Lägg till regler direkt under ett EnabledTracing, EnabledGlobalTracingeller EnabledLocalTracing -avsnitt. Lägg inte till en Rules nivå.

Regelavsnitt

Välj ett regelavsnitt baserat på källomfånget och om regeln riktar sig till en lyssnare:

Avsnitt Matchande lyssnare Matchande aktivitetskällor
EnabledTracing Alla registrerade lyssnare. Globala och lokala källor.
EnabledGlobalTracing Alla registrerade lyssnare. Endast globala källor.
EnabledLocalTracing Alla registrerade lyssnare. Endast lokala källor.
{Listener}:EnabledTracing Den namngivna lyssnaren. Globala och lokala källor.
{Listener}:EnabledGlobalTracing Den namngivna lyssnaren. Endast globala källor.
{Listener}:EnabledLocalTracing Den namngivna lyssnaren. Endast lokala källor.

Lyssnarnamnen matchar namnen som skickas till AddListener. Avsnittsnamn och lyssnarnamn är inte skiftlägeskänsliga.

Regelnivåer

Under alla regelavsnitt använder du något av följande nyckelformulär:

Nyckelformulär Regelnivå Match
Default Default. Varje källa och åtgärd.
{SourceName} Aktivitetskälla. Varje åtgärd från matchande källor.
{SourceName}:Default Aktivitetskälla. Varje åtgärd från matchande källor. Med det här formuläret kan en källa även innehålla åtgärdsregler.
{SourceName}:{OperationName} Operation. Den namngivna åtgärden från matchande källor.

Ange varje lövvärde till true för att aktivera matchningen eller false för att inaktivera den. Till exempel den föregående konfigurationen:

  • Inaktiverar spårning som standard.
  • Aktiverar källor vars namn börjar med Contoso.
  • Aktiverar Contoso.Orders, men inaktiverar dess HealthCheck åtgärd.
  • Aktiverar ett källmönster som börjar med Contoso. och slutar med .Storage.
  • Lägger till regler som endast gäller för globala källor, lokala källor eller lyssnaren med namnet Console.

Använd Default som ett booleskt löv. Om Default innehåller underordnade åtgärder behandlas konfigurationen som ett literalt aktivitetskällanamn Default .

Konfigurera spårning med kod

Anropa EnableTracing och DisableTracing på den som skickats ITracingBuilder till AddTracing.

tracing.EnableTracing(sourceName: "Contoso");
tracing.DisableTracing(
    sourceName: "Contoso.Orders",
    operationName: "HealthCheck");

sourceNameUtelämna , operationNameeller listenerName för att matcha alla värden på den nivån. Som standard gäller en programmatisk regel för både globala och lokala källor. Skicka Global, Local, eller båda genom scopes argumentet för att begränsa regeln.

Konfigurationsregler och programmatiska regler utgör en ordnad regeluppsättning. Om lika specifika regler är i konflikt har regeln lagt till de senaste vinsterna. Ordningen på anrop i återanropet AddTracing spelar därför roll när AddConfiguration, EnableTracingoch DisableTracing lägger till lika specifika regler.

Matcha aktivitetskällans namn

Källnamn, åtgärdsnamn och lyssnarnamn använder skiftlägesokänslig ordningstalsjämförelse. Källnamnsregler stöder följande matchningsformulär:

  • Ett tomt källnamn matchar varje källa.
  • Ett källnamn utan jokertecken matchar med prefix. Till exempel Contoso matchar Contoso.Orders och ContosoPayments– matcharen kräver ingen avgränsare efter prefixet.
  • Ett källnamn med ett * jokertecken matchar ett prefix och suffix. Till exempel Contoso.*.Storage matchar Contoso.Orders.Storage, men inte Contoso.Orders.Api.
  • Ett källnamn för * matchar varje källa.

Åtgärdsnamnen matchar exakt. De använder inte prefix eller jokerteckenmatchning.

Tillämpa regelprioret

För varje lyssnare, källa, åtgärd och omfångskombination väljer spårningsinfrastrukturen en matchande regel. Den jämför matchande regler i den här ordningen:

  • En lyssnarspecifik regel har företräde framför en regel för alla lyssnare.
  • En källregel har företräde framför en standardregel. Om två källuttryck matchar har det längre uttrycket företräde. Jämförelsen använder uttryckslängden, inklusive ett * jokertecken.
  • En åtgärdsregel har företräde framför en regel på källnivå.
  • En regel endast globalt eller lokalt har företräde framför en regel som omfattar båda omfången.
  • Den sista regeln har företräde när alla föregående faktorer är lika.

Jämförelsen stoppas vid den första skillnaden. Till exempel har en lyssnarspecifik standardregel företräde framför en källspecifik regel som gäller för alla lyssnare eftersom lyssnarens specificitet utvärderas först.

Åtgärdsregler styr även källprenumerationer. En lyssnare prenumererar på en källa som är inaktiverad som standard när en åtgärdsregel aktiverar minst en åtgärd från den källan. Lyssnaren returnerar None och hoppar sedan över sina återanrop för inaktiverade åtgärder.

Välj globala eller lokala aktivitetskällor

Spårningsinfrastrukturen skiljer två aktivitetskällans omfång:

  • En global källa skapas ActivitySource via konstruktorn. EnabledGlobalTracing gäller för dessa källor.
  • En lokal källa är en ActivitySource som skapas av den ActivitySourceFactory lösta från beroendeinmatningen. EnabledLocalTracing regler gäller för källor som skapats av fabriken.

Använd Create när du vill att containern för beroendeinmatning ska hantera källan och dess spårningslyssnare. En fabriks lyssnare ignorerar lokala källor som skapats av en annan fabrik. Regler i EnabledTracing gäller för båda källtyperna.

Dessa omfång begränsar endast de lyssnare som AddTracing registreras. En oberoende ActivityListener använder sina egna ShouldListenTo och samplingsåteranrop, även för en aktivitetskälla som skapats av ActivitySourceFactory.

Läsa in spårningskonfigurationen igen

AddConfiguration prenumererar på ändringstoken från den angivna konfigurationen. När en konfigurationsprovider har stöd för att läsa in och rapporterar en ändring, kommer spårningsinfrastrukturen:

  • Återskapar regeluppsättningen.
  • Uppdaterar varje registrerad lyssnares källprenumerationer.
  • Tillämpar de uppdaterade reglerna på efterföljande aktiviteter.

Appen kan fortsätta att använda samma ActivitySource instanser efter en ny inläsning. Efterföljande aktiviteter använder de uppdaterade reglerna.

För en föränderlig provider som inte rapporterar ändringar automatiskt uppdaterar du konfigurationen och anropar Reload. Det fullständiga exemplet använder den här metoden med den minnesinterna konfigurationsprovidern.

Hantera ogiltig konfiguration

Spårningskonfiguration parsar värden med TryParse. Den accepterar true och false utan hänsyn till skiftläge och tillstånd kring blanksteg. Den accepterar 1inte , 0, yeseller on.

Konfigurationsinläsaren ignorerar tyst ett lövvärde som inte är ett giltigt booleskt värde. Den ignorerar också okända eller felaktiga avsnitt som inte matchar schemat som stöds. Kontrollera nyckelnamn noggrant eftersom dessa fall inte ger upphov till något undantag.

Ett källuttryck kan innehålla högst ett * jokertecken. En regel med mer än ett jokertecken genererar en ArgumentException när regeln materialiseras, antingen under appstart eller efter att konfigurationen har lästs in igen. För programmatiska regler None orsakar även en ArgumentOutOfRangeException.

Kör det här exemplet

Följande .NET 11-konsolapp skapar en aktiverad åtgärd och en inaktiverad åtgärd. Den uppdaterar sedan regeln för den inaktiverade åtgärden, anropar Reloadoch startar åtgärden igen via samma lokala ActivitySource.

using System.Diagnostics;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.Tracing;

IConfigurationRoot configuration = new ConfigurationBuilder()
    .AddInMemoryCollection(new Dictionary<string, string?>
    {
        ["Tracing:EnabledTracing:Default"] = "false",
        ["Tracing:EnabledTracing:Contoso.Orders:Default"] = "true",
        ["Tracing:EnabledTracing:Contoso.Orders:DisabledOperation"] = "false",
    })
    .Build();

ServiceCollection services = new();
services.AddTracing(tracing =>
{
    tracing.AddListener("Console", listener =>
    {
        listener.Sample = static (ref ActivityCreationOptions<ActivityContext> _) =>
            ActivitySamplingResult.AllData;
        listener.SampleUsingParentId = static (ref ActivityCreationOptions<string> _) =>
            ActivitySamplingResult.AllData;
        listener.ActivityStarted = activity =>
            Console.WriteLine($"Listener started: {activity.OperationName}");
    });
    tracing.AddConfiguration(configuration.GetSection("Tracing"));
});

using ServiceProvider serviceProvider = services.BuildServiceProvider();
ActivitySourceFactory factory =
    serviceProvider.GetRequiredService<ActivitySourceFactory>();
using ActivitySource source = factory.Create("Contoso.Orders");

Console.WriteLine("Before reload:");
WriteResult(source, "EnabledOperation");
WriteResult(source, "DisabledOperation");

configuration["Tracing:EnabledTracing:Contoso.Orders:DisabledOperation"] = "true";
configuration.Reload();

Console.WriteLine("After reload:");
WriteResult(source, "DisabledOperation");

static void WriteResult(ActivitySource source, string operationName)
{
    using Activity? activity = source.StartActivity(operationName);
    string state = activity is null ? "disabled" : "enabled";
    Console.WriteLine($"{operationName}: {state}");
}
Imports System.Diagnostics
Imports Microsoft.Extensions.Configuration
Imports Microsoft.Extensions.DependencyInjection
Imports Microsoft.Extensions.Diagnostics.Tracing

Module Program
    Sub Main()
        Dim initialData As New Dictionary(Of String, String) From {
            {"Tracing:EnabledTracing:Default", "false"},
            {"Tracing:EnabledTracing:Contoso.Orders:Default", "true"},
            {"Tracing:EnabledTracing:Contoso.Orders:DisabledOperation", "false"}
        }

        Dim configuration As IConfigurationRoot =
            New ConfigurationBuilder().AddInMemoryCollection(initialData).Build()

        Dim services As New ServiceCollection()
        services.AddTracing(
            Sub(tracing)
                tracing.AddListener(
                    "Console",
                    Sub(listener)
                        listener.Sample = AddressOf SampleActivity
                        listener.SampleUsingParentId = AddressOf SampleActivityUsingParentId
                        listener.ActivityStarted =
                            Sub(activity) Console.WriteLine(
                                $"Listener started: {activity.OperationName}")
                    End Sub)
                tracing.AddConfiguration(configuration.GetSection("Tracing"))
            End Sub)

        Using serviceProvider As ServiceProvider = services.BuildServiceProvider()
            Dim factory As ActivitySourceFactory =
                serviceProvider.GetRequiredService(Of ActivitySourceFactory)()

            Using source As ActivitySource = factory.Create("Contoso.Orders")
                Console.WriteLine("Before reload:")
                WriteResult(source, "EnabledOperation")
                WriteResult(source, "DisabledOperation")

                configuration(
                    "Tracing:EnabledTracing:Contoso.Orders:DisabledOperation") = "true"
                configuration.Reload()

                Console.WriteLine("After reload:")
                WriteResult(source, "DisabledOperation")
            End Using
        End Using
    End Sub

    Private Function SampleActivity(
        ByRef options As ActivityCreationOptions(Of ActivityContext)
    ) As ActivitySamplingResult
        Return ActivitySamplingResult.AllData
    End Function

    Private Function SampleActivityUsingParentId(
        ByRef options As ActivityCreationOptions(Of String)
    ) As ActivitySamplingResult
        Return ActivitySamplingResult.AllData
    End Function

    Private Sub WriteResult(source As ActivitySource, operationName As String)
        Using activity As Activity = source.StartActivity(operationName)
            Dim state As String = If(activity Is Nothing, "disabled", "enabled")
            Console.WriteLine($"{operationName}: {state}")
        End Using
    End Sub
End Module

Exemplen C# och Visual Basic ger samma resultat:

Before reload:
Listener started: EnabledOperation
EnabledOperation: enabled
DisabledOperation: disabled
After reload:
Listener started: DisabledOperation
DisabledOperation: enabled

Se även