Jazyk

Konfigurace distribuovaného trasování v .NET

V .NET 11 a novějších Microsoft.Extensions.Diagnostics.Tracing rozhraní API umožňují registrovat ActivityListener instance a používat pravidla k výběru ActivitySource instancí a Activity instancí, které každý posluchač obdrží. Definujte pravidla v kódu nebo je načtěte z IConfiguration.

Important

Pravidla trasování ovlivňují pouze nasluchače zaregistrované prostřednictvím této infrastruktury trasování. Nemají vliv na nesouvisející ActivityListener instance, včetně listenerů, které exportátoři telemetrie vytvářejí a spravují. Tyto listenery nebo vývozce nakonfigurujte samostatně.

Trasování registru

Rozhraní API jsou k dispozici v Microsoft.Extensions.Diagnostics balíčku. Aplikace, které odkazují na sdílenou architekturu rozhraní Microsoft.AspNetCore.App, již obsahují sestavení.

Zavolejte AddTracing na IServiceCollection. V callbacku:

  • Zavolejte AddListener, aby se zaregistroval každý naslouchač. Název listeneru identifikuje listener v pravidlech konfigurace.
  • Nakonfigurujte vzorkování dat a delegáty oznámení listeneru prostřednictvím ActivityListenerBuilder. Infrastruktura trasování vlastní ShouldListenTo, zdrojová předplatná a životnost objektu listeneru.
  • Zavolejte AddConfiguration s oddílem konfigurace, který obsahuje pravidla. Pro oddíl s názvem Tracing zadejte configuration.GetSection("Tracing").

Kompletní ukázka ukazuje všechna tři volání. Hostitel .NET aktivuje odběry trasování při spuštění hostitele. Pokud použijete injektování závislostí bez hostitele, získejte zaregistrované ActivitySourceFactory k vytvoření naslouchačů a aktivaci jejich odběrů. Kompletní ukázka přímo získá factory.

Konfigurovat trasování

Nastavte pravidla trasování prostřednictvím konfigurace nebo kódu. Pokud žádné pravidlo neodpovídá nasluchači, zdroji, operaci a oboru, trasování zůstane pro danou kombinaci zakázané.

Konfigurace trasování bez kódu

Pro aplikace, které používají konfiguraci, přidejte oddíl Tracing do appsettings.json nebo jiného poskytovatele konfigurace. Pak předejte tuto sekci AddConfiguration:

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

Následující příklad ukazuje podporované části pravidel a úrovně pravidel:

{
  "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
        }
      }
    }
  }
}

Přidejte pravidla přímo pod oddíl EnabledTracing, EnabledGlobalTracing nebo EnabledLocalTracing. Nepřidávejte úroveň Rules.

Oddíly pravidel

Zvolte oddíl pravidla na základě rozsahu zdroje a toho, zda pravidlo cílí na jeden listener:

Sekce Odpovídající listenery Shodné zdroje aktivit
EnabledTracing Všichni registrovaní posluchači. Globální a místní zdroje
EnabledGlobalTracing Všechny registrované listenery. Pouze globální zdroje.
EnabledLocalTracing Všechny registrované listenery. Pouze místní zdroje.
{Listener}:EnabledTracing Pojmenovaný listener. Globální a místní zdroje
{Listener}:EnabledGlobalTracing Pojmenovaný listener. Pouze globální zdroje.
{Listener}:EnabledLocalTracing Pojmenovaný listener. Pouze místní zdroje.

Názvy listenerů odpovídají názvům předaným AddListener. Názvy oddílů a názvy listenerů nerozlišují malá a velká písmena.

Úrovně pravidel

V libovolné části pravidla použijte jednu z následujících forem klíčů:

Typ klíče Úroveň pravidla Párování
Default Výchozí. Každý zdroj a každá operace.
{SourceName} Zdroj aktivity. Každá operace pro odpovídající zdroje.
{SourceName}:Default Zdroj aktivity. Každá operace z porovnávaných zdrojů. Tento formulář umožňuje, aby zdroj také obsahoval pravidla operací.
{SourceName}:{OperationName} Operace. Pojmenovaná operace z odpovídajících zdrojů.

Nastavte každou hodnotu listu na true pro povolení shody nebo na false pro její zakázání. Například předchozí konfigurace:

  • Zakáže trasování ve výchozím nastavení.
  • Povolí zdroje, jejichž názvy začínají Contoso.
  • Contoso.OrdersPovolí , ale zakáže jeho HealthCheck operaci.
  • Umožňuje zdrojový vzor, který začíná Contoso. a končí na .Storage.
  • Přidá pravidla, která se vztahují pouze na globální zdroje, místní zdroje nebo listener s názvem Console.

Použijte Default jako booleovský list. Pokud Default obsahuje podřízené operace, konfigurace považuje Default za doslovný název zdroje aktivity.

Nakonfigurujte trasování pomocí kódu

Zavolejte EnableTracing a DisableTracing na ITracingBuilder předaném do AddTracing.

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

Vynechejte operationName, listenerName nebo sourceName, aby odpovídaly všem hodnotám na této úrovni. Ve výchozím nastavení se pravidlo definované programově vztahuje na globální i místní zdroje. Předáním Global, Local nebo obojího prostřednictvím argumentu scopes zúžíte pravidlo.

Pravidla konfigurace a programatická pravidla tvoří jednu seřazenou sadu pravidel. Pokud dojde ke konfliktu stejně specifických pravidel, pravidlo přidané jako poslední vyhrává. Pořadí volání ve zpětném volání AddTracing proto záleží na tom, když EnableTracing, AddConfiguration a DisableTracing přidávají stejně specifická pravidla.

Porovnat názvy zdrojů aktivit

Názvy zdrojů, názvy operací a názvy naslouchačů používají řadové porovnání bez rozlišování velkých a malých písmen. Pravidla zdrojového názvu podporují tyto formuláře shody:

  • Prázdný název zdroje odpovídá každému zdroji.
  • Název zdroje bez zástupného znaku se shoduje podle prefixu. Například Contoso odpovídá Contoso.Orders a ContosoPayments; matcher nevyžaduje oddělovač za předponou.
  • Název zdroje s jedním zástupným znakem * odpovídá prefixu i sufixu. Například Contoso.*.Storage odpovídá Contoso.Orders.Storage, ale ne Contoso.Orders.Api.
  • Název zdroje * odpovídá každému zdroji.

Názvy operací přesně odpovídají. Nepoužívají shodu podle prefixu ani porovnávání se zástupnými znaky.

Použít prioritu pravidel

Pro každou kombinaci listeneru, zdroje, operace a rozsahu zvolí infrastruktura trasování jedno odpovídající pravidlo. Porovnává odpovídající pravidla v tomto pořadí:

  • Pravidlo specifické pro listener má přednost před pravidlem pro všechny listenery.
  • Zdrojové pravidlo má přednost před výchozím pravidlem. Pokud se shodují dva zdrojové výrazy, má delší výraz přednost. Porovnání používá délku výrazu, včetně zástupného znaku *.
  • Pravidlo operace má přednost před pravidlem na úrovni zdroje.
  • Globální nebo místní pravidlo má přednost před pravidlem, které pokrývá oba rozsahy.
  • Poslední pravidlo má přednost, pokud jsou všechny předchozí faktory stejné.

Porovnání se zastaví na prvním rozdílu. Výchozí pravidlo specifické pro listener má například přednost před zdrojovým pravidlem, které platí pro všechny listenery, protože se nejprve vyhodnotí specificita listeneru.

Pravidla operací také řídí odběry zdrojů. Listener se přihlásí k odběru zdroje, který je ve výchozím nastavení zakázaný, když pravidlo operace povolí alespoň jednu operaci z tohoto zdroje. Naslouchač pak vrátí None a přeskočí zpětná volání pro zakázané operace.

Vyberte globální nebo místní zdroje aktivit

Infrastruktura trasování rozlišuje dvě oblasti zdroje aktivit:

  • Globální zdroj je ActivitySourceinstance vytvořená prostřednictvím svého konstruktoru. EnabledGlobalTracing pravidla se vztahují na tyto zdroje.
  • Místní zdroj je ActivitySource vytvořený pomocí ActivitySourceFactory vyřešeného z injektování závislostí. EnabledLocalTracing pravidla se vztahují na zdroje vytvořené danou továrnou.

Použijte Create, když chcete, aby kontejner pro injektáž závislostí spravoval zdroj a jeho posluchače trasování. Listenery factory ignorují místní zdroje vytvořené jinou factory. EnabledTracing Pravidla platí pro oba typy zdrojů.

Tyto oblasti omezují pouze posluchače, které registruje AddTracing. Nezávislý ActivityListener používá vlastní ShouldListenTo a zpětná volání pro vzorkování, a to i pro zdroj aktivity vytvořený pomocí ActivitySourceFactory.

Znovu načíst konfiguraci trasování

AddConfiguration přihlásí se k odběru tokenu změny ze zadané konfigurace. Pokud poskytovatel konfigurace podporuje opětovné načítání a hlásí změnu, trasovací infrastruktura:

  • Znovu sestaví sadu pravidel.
  • Aktualizuje zdrojové odběry každého registrovaného nasluchače.
  • Použije aktualizovaná pravidla na následné aktivity.

Aplikace může po opětovném načtení dál používat stejné ActivitySource instance. Následné aktivity používají aktualizovaná pravidla.

U proměnlivého poskytovatele, který nehlásí změny automaticky, aktualizujte konfiguraci a zavolejte Reload. Kompletní ukázka používá tento přístup s poskytovatelem konfigurace v paměti.

Zpracovat neplatnou konfiguraci

Konfigurace trasování analyzuje hodnoty pomocí TryParse. Přijímá true a false bez ohledu na velikost písmen a povoluje okolní prázdné znaky. Nepřijímá 1, 0, yes nebo on.

Zavaděč konfigurace bezobslužně ignoruje koncovou hodnotu, která není platnou logickou hodnotou. Ignoruje také neznámé nebo chybně formátované oddíly, které neodpovídají podporovanému schématu. Pečlivě zkontrolujte názvy klíčů, protože tyto případy nevyvolají výjimku.

Zdrojový výraz může obsahovat maximálně jeden * zástupný znak. Pravidlo s více než jedním zástupným znakem vyvolá při materializaci pravidla výjimku ArgumentException, a to buď během spuštění aplikace, nebo po opětovném načtení konfigurace. U programových pravidel také None způsobí ArgumentOutOfRangeException.

Spusťte ukázku

Následující .NET 11 konzolová aplikace vytvoří jednu povolenou operaci a jednu zakázanou operaci. Potom aktualizuje pravidlo pro zakázanou operaci, zavolá Reload a spustí operaci znovu prostřednictvím stejného místního 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

Ukázky jazyka C# a Visual Basic vytvoří stejný výsledek:

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

Viz také