Język

Konfigurowanie śledzenia rozproszonego w .NET

W .NET 11 i nowszych interfejsy API Microsoft.Extensions.Diagnostics.Tracing umożliwiają rejestrowanie instancji ActivityListener i używanie reguł do wybierania instancji ActivitySource i Activity, które odbiera każdy nasłuchiwacz. Zdefiniuj reguły w kodzie lub załaduj je z IConfiguration.

Important

Reguły śledzenia mają wpływ tylko na nasłuchiwacze zarejestrowane za pośrednictwem tej infrastruktury śledzenia. Nie mają one wpływu na niepowiązane ActivityListener wystąpienia, w tym odbiorniki, które eksporterzy telemetrii tworzą i którymi zarządzają. Skonfiguruj te listenery lub eksporterów oddzielnie.

Rejestrowanie trasowania

Interfejsy API są dostępne w pakiecie Microsoft.Extensions.Diagnostics . Aplikacje odwołujące się do Microsoft.AspNetCore.App współdzielonej platformy zawierają już asemblację.

Wywołaj AddTracing na IServiceCollection. W callbacku:

  • Wywołaj AddListener, aby zarejestrować każdy listener. Nazwa listenera identyfikuje listener w regułach konfiguracji.
  • Skonfiguruj delegatów próbkowania i powiadomień odbiornika za pośrednictwem ActivityListenerBuilder. Infrastruktura śledzenia jest właścicielem ShouldListenTo, subskrypcji źródeł i okresu istnienia detektora.
  • Wywołaj AddConfiguration z sekcją konfiguracji zawierającą reguły. W przypadku sekcji o nazwie Tracingprzekaż configuration.GetSection("Tracing").

Kompletny przykład przedstawia wszystkie trzy wywołania. Host .NET aktywuje subskrypcje śledzenia po uruchomieniu hosta. Jeśli używasz iniekcji zależności bez hosta, rozwiąż zarejestrowaną usługę ActivitySourceFactory, aby skonstruować nasłuchiwacze i aktywować ich subskrypcje. Kompletny przykład uzyskuje fabrykę bezpośrednio.

Skonfiguruj śledzenie

Ustaw reguły śledzenia za pomocą konfiguracji lub w kodzie. Jeśli żadna reguła nie pasuje do nasłuchiwacza, źródła, operacji i zakresu, śledzenie pozostanie wyłączone dla tej kombinacji.

Konfigurowanie śledzenia bez kodu

W przypadku aplikacji korzystających z konfiguracji dodaj sekcję Tracing do appsettings.json lub do innego dostawcy konfiguracji. Następnie przekaż tę sekcję do AddConfiguration:

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

W poniższym przykładzie przedstawiono obsługiwane sekcje reguł i poziomy reguł:

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

Dodaj reguły bezpośrednio pod sekcją EnabledTracing, EnabledGlobalTracing lub EnabledLocalTracing. Nie dodawaj poziomu Rules.

Sekcje reguł

Wybierz sekcję reguły na podstawie zakresu źródłowego i tego, czy reguła jest przeznaczona dla jednego odbiorcy nasłuchu:

Section Pasujące detektory Dopasowane źródła aktywności
EnabledTracing Wszystkie zarejestrowane elementy nasłuchujące. Źródła globalne i lokalne.
EnabledGlobalTracing Wszystkie zarejestrowane nasłuchiwacze. Tylko źródła globalne.
EnabledLocalTracing Wszystkie zarejestrowane nasłuchiwacze. Tylko lokalne źródła.
{Listener}:EnabledTracing Nazwany listener. Źródła globalne i lokalne.
{Listener}:EnabledGlobalTracing Nazwany nasłuchiwacz. Tylko źródła globalne.
{Listener}:EnabledLocalTracing Nazwany nasłuchiwacz. Tylko lokalne źródła.

Nazwy odbiorników są zgodne z nazwami przekazanymi do AddListener. Nazwy sekcji i nazwy listenerów nie rozróżniają wielkości liter.

Poziomy reguł

W dowolnej sekcji reguły użyj jednego z następujących formatów klucza:

Formularz klucza Poziom reguły Match
Default Default. Każde źródło i każda operacja.
{SourceName} Źródło aktywności. Każda operacja z dopasowanych źródeł.
{SourceName}:Default Źródło aktywności. Każda operacja z dopasowanych źródeł. Ten formularz pozwala również, aby źródło zawierało reguły operacji.
{SourceName}:{OperationName} Operacja. Nazwana operacja z odpowiadających źródeł.

Ustaw każdą wartość liścia na true, aby włączyć dopasowanie, lub na false, aby je wyłączyć. Na przykład poprzednia konfiguracja:

  • Domyślnie wyłącza śledzenie.
  • Włącza źródła, których nazwy zaczynają się od Contoso.
  • Contoso.OrdersWłącza, ale wyłącza jego działanie HealthCheck.
  • Włącza wzorzec źródłowy rozpoczynający się od Contoso. i kończący się na .Storage.
  • Dodaje reguły, które mają zastosowanie tylko do źródeł globalnych, lokalnych źródeł lub odbiornika o nazwie Console.

Użyj Default jako liścia logicznego. Jeśli element Default zawiera podrzędne operacje, konfiguracja traktuje Default jako dosłowną nazwę źródła działania.

Konfigurowanie śledzenia przy użyciu kodu

Wywołaj metodę EnableTracing i DisableTracing na ITracingBuilder przekazanym do AddTracing.

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

Pomiń sourceName, operationName lub listenerName, aby dopasować wszystkie wartości na tym poziomie. Domyślnie reguła programowa ma zastosowanie zarówno do źródeł globalnych, jak i lokalnych. Przekaż Global, Local lub oba te elementy za pomocą argumentu scopes, aby zawęzić regułę.

Reguły konfiguracji i reguły programowe tworzą jeden uporządkowany zestaw reguł. Jeśli równie szczegółowe reguły są sprzeczne, wygrywa reguła dodana jako ostatnia. W związku z tym kolejność wywołań w wywołaniu zwrotnym AddTracing ma znaczenie, gdy AddConfiguration, EnableTracingi DisableTracing dodają równie specyficzne reguły.

Dopasuj nazwy źródeł działań

Nazwy źródeł, nazwy operacji i nazwy listenerów używają porównania porządkowego bez uwzględniania wielkości liter. Reguły nazw źródłowych obsługują te formy dopasowania:

  • Pusta nazwa źródła pasuje do każdego źródła.
  • Nazwa źródła bez symbolu wieloznakowego jest dopasowywana na podstawie prefiksu. Na przykład Contoso dopasowuje Contoso.Orders i ContosoPayments; moduł dopasowujący nie wymaga separatora po prefiksie.
  • Nazwa źródła z jednym * symbolem wieloznacznym odpowiada nazwie z tym prefiksem i sufiksem. Na przykład Contoso.*.Storage pasuje do Contoso.Orders.Api, ale nie do Contoso.Orders.Storage.
  • Nazwa źródła * pasuje do każdego źródła.

Nazwy operacji są dokładnie zgodne. Nie używają prefiksów ani dopasowywania symboli wieloznacznych.

Zastosuj priorytet reguły

Dla każdego odbiornika, źródła, operacji i kombinacji zakresu infrastruktura śledzenia wybiera jedną pasującą regułę. Porównuje reguły dopasowania w następującej kolejności:

  • Reguła specyficzna dla listenera ma pierwszeństwo przed regułą dla wszystkich listenerów.
  • Reguła źródłowa ma pierwszeństwo przed regułą domyślną. Jeśli dwa wyrażenia źródłowe pasują, dłuższe wyrażenie ma pierwszeństwo. Porównanie używa długości wyrażenia, w tym symbol wieloznaczny *.
  • Reguła operacji ma pierwszeństwo przed regułą na poziomie źródła.
  • Reguła tylko globalna lub tylko lokalna ma pierwszeństwo przed regułą obejmującą oba zakresy.
  • Ostatnia reguła ma pierwszeństwo, gdy wszystkie poprzednie czynniki są równe.

Porównanie zatrzymuje się na pierwszej różnicy. Na przykład reguła domyślna specyficzna dla listenera ma pierwszeństwo przed regułą specyficzną dla źródła, która ma zastosowanie do wszystkich listenerów, ponieważ specyfika listenera jest oceniana jako pierwsza.

Reguły operacyjne kontrolują również subskrypcje źródłowe. Odbiornik subskrybuje źródło, które jest domyślnie wyłączone, ale zostaje aktywowane, gdy reguła operacji włącza co najmniej jedną operację z tego źródła. Następnie odbiornik zwraca None i pomija wywołania zwrotne dla wyłączonych operacji.

Wybierz globalne lub lokalne źródła aktywności

Infrastruktura śledzenia rozróżnia dwa zakresy źródeł aktywności:

  • Źródło globalne jest ActivitySource tworzone przez swój konstruktor. EnabledGlobalTracing reguły mają zastosowanie do tych źródeł.
  • Lokalne źródło jest ActivitySource tworzone przez ActivitySourceFactory uzyskane za pomocą wstrzykiwania zależności. EnabledLocalTracing reguły mają zastosowanie do źródeł utworzonych przez tę fabrykę.

Użyj Create polecenia , jeśli chcesz, aby kontener wstrzykiwania zależności zarządzał źródłem i jego odbiornikami śledzenia. Nasłuchiwacze fabryki ignorują lokalne źródła utworzone przez inną fabrykę. Reguły w EnabledTracing mają zastosowanie do obu typów źródeł.

Te zakresy ograniczają tylko odbiorniki rejestrowane przez AddTracing. Niezależny ActivityListener używa własnych ShouldListenTo wywołań zwrotnych i funkcji próbkowania, nawet w przypadku źródła aktywności utworzonego przez ActivitySourceFactory program.

Załaduj ponownie konfigurację śledzenia

AddConfiguration subskrybuje token zmian pochodzący z podanej konfiguracji. Gdy dostawca konfiguracji obsługuje ponowne ładowanie i zgłasza zmianę, infrastruktura śledzenia:

  • Ponownie kompiluje zestaw reguł.
  • Odświeża subskrypcje źródłowe każdego zarejestrowanego nasłuchiwacza.
  • Stosuje zaktualizowane reguły do kolejnych działań.

Aplikacja może nadal używać tych samych ActivitySource wystąpień po ponownym załadowaniu. Kolejne działania używają zaktualizowanych reguł.

W przypadku dostawcy modyfikowalnego, który nie zgłasza zmian automatycznie, zaktualizuj konfigurację i wywołaj metodę Reload. Kompletny przykład używa tego podejścia z dostawcą konfiguracji w pamięci.

Obsłuż nieprawidłową konfigurację

Konfiguracja śledzenia analizuje wartości przy użyciu TryParse. Akceptuje true i false bez rozróżniania wielkości liter i dopuszcza otaczające białe znaki. Nie akceptuje 1, 0, yes lub on.

Moduł ładujący konfiguracji dyskretnie ignoruje wartość liścia, która nie jest prawidłową wartością logiczną. Ignoruje również nieznane lub nieprawidłowo sformatowane sekcje, które nie są zgodne z obsługiwanym schematem. Dokładnie sprawdź nazwy kluczy, ponieważ te przypadki nie generują wyjątku.

Wyrażenie źródłowe może zawierać co najwyżej jeden * symbol wieloznaczny. Reguła z więcej niż jednym symbolem wieloznacznym zgłasza ArgumentException błąd, gdy reguła zostanie zmaterializowana podczas uruchamiania aplikacji lub po ponownym załadowaniu konfiguracji. W przypadku programistycznych reguł None powoduje również ArgumentOutOfRangeException.

Uruchamianie aplikacji przykładowej

Następująca .NET 11 aplikacja konsolowa tworzy jedną włączoną operację i jedną wyłączoną operację. Następnie aktualizuje regułę wyłączonej operacji, wywołuje metodę Reload i ponownie uruchamia operację za pośrednictwem tego samego lokalnego 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

Przykłady języka C# i Visual Basic dają ten sam wynik:

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

Informacje dodatkowe