Śledzenie operacji niestandardowych przy użyciu zestawu SDK platformy .NET Szczegółowe informacje aplikacji

Zestawy SDK Szczegółowe informacje aplikacji automatycznie śledzą przychodzące żądania HTTP i wywołania usług zależnych, takich jak żądania HTTP i zapytania SQL. Śledzenie i korelacja żądań i zależności zapewnia wgląd w czas odpowiedzi i niezawodność całej aplikacji we wszystkich mikrousługach łączących tę aplikację.

Istnieje klasa wzorców aplikacji, których nie można ogólnie obsługiwać. Odpowiednie monitorowanie takich wzorców wymaga instrumentacji kodu ręcznego. W tym artykule opisano kilka wzorców, które mogą wymagać instrumentacji ręcznej, takich jak niestandardowe przetwarzanie kolejek i długotrwałe zadania w tle.

Ten artykuł zawiera wskazówki dotyczące śledzenia operacji niestandardowych przy użyciu zestawu SDK usługi Application Szczegółowe informacje. Ta dokumentacja jest odpowiednia dla:

  • Szczegółowe informacje aplikacji dla platformy .NET (znanej również jako podstawowy zestaw SDK) w wersji 2.4 lub nowszej.
  • Aplikacja Szczegółowe informacje dla aplikacji internetowych (z systemem ASP.NET) w wersji 2.4 lub nowszej.
  • Szczegółowe informacje aplikacji dla ASP.NET Core w wersji 2.1 lub nowszej.

Uwaga

Poniższa dokumentacja opiera się na klasycznym interfejsie API usługi Application Szczegółowe informacje. Długoterminowy plan Szczegółowe informacje aplikacji polega na zbieraniu danych przy użyciu biblioteki OpenTelemetry. Aby uzyskać więcej informacji, zobacz Enable Azure Monitor OpenTelemetry for .NET, Node.js, Python and Java applications (Włączanie usługi Azure Monitor OpenTelemetry dla platformy .NET, Node.js, Python i Java applications).

Omówienie

Operacja jest logicznym elementem pracy uruchamianym przez aplikację. Ma on nazwę, czas rozpoczęcia, czas trwania, wynik i kontekst wykonywania, taki jak nazwa użytkownika, właściwości i wynik. Jeśli operacja A została zainicjowana przez operację B, operacja B jest ustawiona jako element nadrzędny dla A. Operacja może mieć tylko jeden element nadrzędny, ale może mieć wiele operacji podrzędnych. Aby uzyskać więcej informacji na temat operacji i korelacji telemetrii, zobacz Korelacja telemetrii Szczegółowe informacje aplikacji.

W Szczegółowe informacje aplikacji .NET SDK operacja jest opisana przez abstrakcyjną klasę OperationTelemetry i jej elementy potomne RequestTelemetry i DependencyTelemetry.

Śledzenie operacji przychodzących

Zestaw SDK aplikacji Szczegółowe informacje sieci Web automatycznie zbiera żądania HTTP dla aplikacji ASP.NET uruchamianych w potoku usług IIS i wszystkich aplikacji ASP.NET Core. Istnieją rozwiązania obsługiwane przez społeczność dla innych platform i struktur. Jeśli aplikacja nie jest obsługiwana przez żadne ze standardowych lub obsługiwanych przez społeczność rozwiązań, możesz przeprowadzić instrumentację ręcznie.

Innym przykładem, który wymaga śledzenia niestandardowego, jest proces roboczy, który odbiera elementy z kolejki. W przypadku niektórych kolejek wywołanie dodawania komunikatu do tej kolejki jest śledzone jako zależność. Operacja wysokiego poziomu, która opisuje przetwarzanie komunikatów, nie jest automatycznie zbierana.

Zobaczmy, jak można śledzić takie operacje.

Na wysokim poziomie zadaniem jest utworzenie RequestTelemetry i ustawienie znanych właściwości. Po zakończeniu operacji można śledzić dane telemetryczne. W poniższym przykładzie pokazano to zadanie.

Żądanie HTTP w aplikacji hostowanej samodzielnie przez firmę Owin

W tym przykładzie kontekst śledzenia jest propagowany zgodnie z protokołem HTTP dla korelacji. Należy spodziewać się otrzymania nagłówków, które zostały tam opisane.

public class ApplicationInsightsMiddleware : OwinMiddleware
{
    // You may create a new TelemetryConfiguration instance, reuse one you already have,
    // or fetch the instance created by Application Insights SDK.
    private readonly TelemetryConfiguration telemetryConfiguration = TelemetryConfiguration.CreateDefault();
    private readonly TelemetryClient telemetryClient = new TelemetryClient(telemetryConfiguration);
    
    public ApplicationInsightsMiddleware(OwinMiddleware next) : base(next) {}

    public override async Task Invoke(IOwinContext context)
    {
        // Let's create and start RequestTelemetry.
        var requestTelemetry = new RequestTelemetry
        {
            Name = $"{context.Request.Method} {context.Request.Uri.GetLeftPart(UriPartial.Path)}"
        };

        // If there is a Request-Id received from the upstream service, set the telemetry context accordingly.
        if (context.Request.Headers.ContainsKey("Request-Id"))
        {
            var requestId = context.Request.Headers.Get("Request-Id");
            // Get the operation ID from the Request-Id (if you follow the HTTP Protocol for Correlation).
            requestTelemetry.Context.Operation.Id = GetOperationId(requestId);
            requestTelemetry.Context.Operation.ParentId = requestId;
        }

        // StartOperation is a helper method that allows correlation of 
        // current operations with nested operations/telemetry
        // and initializes start time and duration on telemetry items.
        var operation = telemetryClient.StartOperation(requestTelemetry);

        // Process the request.
        try
        {
            await Next.Invoke(context);
        }
        catch (Exception e)
        {
            requestTelemetry.Success = false;
            requestTelemetry.ResponseCode;
            telemetryClient.TrackException(e);
            throw;
        }
        finally
        {
            // Update status code and success as appropriate.
            if (context.Response != null)
            {
                requestTelemetry.ResponseCode = context.Response.StatusCode.ToString();
                requestTelemetry.Success = context.Response.StatusCode >= 200 && context.Response.StatusCode <= 299;
            }
            else
            {
                requestTelemetry.Success = false;
            }

            // Now it's time to stop the operation (and track telemetry).
            telemetryClient.StopOperation(operation);
        }
    }
    
    public static string GetOperationId(string id)
    {
        // Returns the root ID from the '|' to the first '.' if any.
        int rootEnd = id.IndexOf('.');
        if (rootEnd < 0)
            rootEnd = id.Length;

        int rootStart = id[0] == '|' ? 1 : 0;
        return id.Substring(rootStart, rootEnd - rootStart);
    }
}

Protokół HTTP dla korelacji deklaruje Correlation-Context również nagłówek . Pominięto go tutaj dla uproszczenia.

Instrumentacja kolejki

Kontekst śledzenia W3C i protokół HTTP dla szczegółów korelacji przekazywania korelacji z żądaniami HTTP, ale każdy protokół kolejki musi określić, jak te same szczegóły są przekazywane wzdłuż komunikatu kolejki. Niektóre protokoły kolejki, takie jak AMQP, umożliwiają przekazywanie większej liczby metadanych. Inne protokoły, takie jak kolejka usługi Azure Storage, wymagają kodowania kontekstu w ładunku komunikatu.

Uwaga

Śledzenie między składnikami nie jest jeszcze obsługiwane w przypadku kolejek.

W przypadku protokołu HTTP, jeśli producent i odbiorca wysyłają dane telemetryczne do różnych zasobów usługi Application Szczegółowe informacje, środowisko diagnostyki transakcji i mapa aplikacji pokazują transakcje i mapuj na koniec. W przypadku kolejek ta funkcja nie jest jeszcze obsługiwana.

Kolejka usługi Service Bus

Aby uzyskać informacje o śledzeniu, zobacz Śledzenie rozproszone i korelacja za pośrednictwem komunikatów usługi Azure Service Bus.

Kolejka usługi Azure Storage

W poniższym przykładzie pokazano, jak śledzić operacje kolejki usługi Azure Storage i korelować dane telemetryczne między producentem, konsumentem i usługą Azure Storage.

Kolejka usługi Storage ma interfejs API HTTP. Wszystkie wywołania kolejki są śledzone przez moduł zbierający zależności aplikacji Szczegółowe informacje dla żądań HTTP. Jest ona domyślnie konfigurowana w aplikacjach ASP.NET i ASP.NET Core. W przypadku innych rodzajów aplikacji zapoznaj się z dokumentacją aplikacji konsolowych.

Możesz również skorelować identyfikator operacji Szczegółowe informacje aplikacji z identyfikatorem żądania magazynu. Aby uzyskać informacje na temat ustawiania i pobierania klienta żądania magazynu oraz identyfikatora żądania serwera, zobacz Monitorowanie, diagnozowanie i rozwiązywanie problemów z usługą Azure Storage.

Kolejka

Ponieważ kolejki usługi Storage obsługują interfejs API HTTP, wszystkie operacje z kolejką są automatycznie śledzone przez aplikację Szczegółowe informacje. W wielu przypadkach instrumentacja ta powinna wystarczyć. Aby skorelować ślady po stronie konsumenta ze śladami producenta, należy przekazać jakiś kontekst korelacji podobnie do tego, jak robimy to w protokole HTTP dla korelacji.

W tym przykładzie pokazano, jak śledzić operację Enqueue . Masz następujące możliwości:

  • Koreluj ponawianie prób (jeśli istnieje): wszystkie mają jeden wspólny element nadrzędny, który jest operacją Enqueue . W przeciwnym razie są one śledzone jako elementy podrzędne żądania przychodzącego. Jeśli istnieje wiele logicznych żądań do kolejki, może być trudno znaleźć wywołanie, które spowodowało ponowne próby.
  • Skoreluj dzienniki magazynu (jeśli i w razie potrzeby): są one skorelowane z danymi telemetrycznymi usługi Application Szczegółowe informacje.

Operacja Enqueue jest elementem podrzędnym operacji nadrzędnej. Przykładem jest przychodzące żądanie HTTP. Wywołanie zależności HTTP jest elementem podrzędnym Enqueue operacji i wnukiem żądania przychodzącego.

public async Task Enqueue(CloudQueue queue, string message)
{
    var operation = telemetryClient.StartOperation<DependencyTelemetry>("enqueue " + queue.Name);
    operation.Telemetry.Type = "Azure queue";
    operation.Telemetry.Data = "Enqueue " + queue.Name;

    // MessagePayload represents your custom message and also serializes correlation identifiers into payload.
    // For example, if you choose to pass payload serialized to JSON, it might look like
    // {'RootId' : 'some-id', 'ParentId' : '|some-id.1.2.3.', 'message' : 'your message to process'}
    var jsonPayload = JsonConvert.SerializeObject(new MessagePayload
    {
        RootId = operation.Telemetry.Context.Operation.Id,
        ParentId = operation.Telemetry.Id,
        Payload = message
    });
    
    CloudQueueMessage queueMessage = new CloudQueueMessage(jsonPayload);

    // Add operation.Telemetry.Id to the OperationContext to correlate Storage logs and Application Insights telemetry.
    OperationContext context = new OperationContext { ClientRequestID = operation.Telemetry.Id};

    try
    {
        await queue.AddMessageAsync(queueMessage, null, null, new QueueRequestOptions(), context);
    }
    catch (StorageException e)
    {
        operation.Telemetry.Properties.Add("AzureServiceRequestID", e.RequestInformation.ServiceRequestID);
        operation.Telemetry.Success = false;
        operation.Telemetry.ResultCode = e.RequestInformation.HttpStatusCode.ToString();
        telemetryClient.TrackException(e);
    }
    finally
    {
        // Update status code and success as appropriate.
        telemetryClient.StopOperation(operation);
    }
}  

Aby zmniejszyć ilość danych telemetrycznych raportów aplikacji lub jeśli nie chcesz śledzić Enqueue operacji z innych powodów, użyj interfejsu Activity API bezpośrednio:

  • Utwórz (i uruchom) nową Activity zamiast uruchamiać operację application Szczegółowe informacje. Nie trzeba przypisywać żadnych właściwości z wyjątkiem nazwy operacji.
  • Serializuj yourActivity.Id w ładunku komunikatu zamiast operation.Telemetry.Id. Możesz również użyć polecenia Activity.Current.Id.

Usuwanie z kolejki

Podobnie jak Enqueuew przypadku usługi , rzeczywiste żądanie HTTP do kolejki usługi Storage jest automatycznie śledzone przez aplikację Szczegółowe informacje. Prawdopodobnie Enqueue operacja odbywa się w kontekście nadrzędnym, takim jak kontekst żądania przychodzącego. Zestawy SDK aplikacji Szczegółowe informacje automatycznie korelują taką operację i jej część HTTP z żądaniem nadrzędnym i innymi danymi telemetrycznymi zgłoszonymi w tym samym zakresie.

Operacja Dequeue jest trudna. Zestaw SDK Szczegółowe informacje aplikacji automatycznie śledzi żądania HTTP. Nie wie jednak kontekstu korelacji, dopóki komunikat nie zostanie przeanalizowany. Nie można skorelować żądania HTTP w celu pobrania komunikatu z pozostałą częścią telemetrii, zwłaszcza w przypadku odebrania więcej niż jednego komunikatu.

public async Task<MessagePayload> Dequeue(CloudQueue queue)
{
    var operation = telemetryClient.StartOperation<DependencyTelemetry>("dequeue " + queue.Name);
    operation.Telemetry.Type = "Azure queue";
    operation.Telemetry.Data = "Dequeue " + queue.Name;
    
    try
    {
        var message = await queue.GetMessageAsync();
    }
    catch (StorageException e)
    {
        operation.telemetry.Properties.Add("AzureServiceRequestID", e.RequestInformation.ServiceRequestID);
        operation.telemetry.Success = false;
        operation.telemetry.ResultCode = e.RequestInformation.HttpStatusCode.ToString();
        telemetryClient.TrackException(e);
    }
    finally
    {
        // Update status code and success as appropriate.
        telemetryClient.StopOperation(operation);
    }

    return null;
}

Przetwarzaj

W poniższym przykładzie komunikat przychodzący jest śledzony w sposób podobny do przychodzącego żądania HTTP:

public async Task Process(MessagePayload message)
{
    // After the message is dequeued from the queue, create RequestTelemetry to track its processing.
    RequestTelemetry requestTelemetry = new RequestTelemetry { Name = "process " + queueName };
    
    // It might also make sense to get the name from the message.
    requestTelemetry.Context.Operation.Id = message.RootId;
    requestTelemetry.Context.Operation.ParentId = message.ParentId;

    var operation = telemetryClient.StartOperation(requestTelemetry);

    try
    {
        await ProcessMessage();
    }
    catch (Exception e)
    {
        telemetryClient.TrackException(e);
        throw;
    }
    finally
    {
        // Update status code and success as appropriate.
        telemetryClient.StopOperation(operation);
    }
}

Podobnie można instrumentować inne operacje kolejki. Operację wglądu należy instrumentować w podobny sposób jak operacja dequeue. Instrumentacja operacji zarządzania kolejkami nie jest konieczna. Aplikacja Szczegółowe informacje śledzi operacje, takie jak HTTP, a w większości przypadków wystarczy.

Podczas instrumentowania usuwania komunikatów upewnij się, że ustawiono identyfikatory operacji (korelacji). Alternatywnie możesz użyć interfejsu Activity API. Następnie nie musisz ustawiać identyfikatorów operacji na elementach telemetrii, ponieważ zestaw SDK usługi Application Szczegółowe informacje wykonuje następujące czynności:

  • Utwórz nowy Activity element po utworzeniu elementu z kolejki.
  • Służy Activity.SetParentId(message.ParentId) do korelowania dzienników konsumentów i producentów.
  • Uruchom plik Activity.
  • Śledzenie operacji usuwania z kolejki, przetwarzania i usuwania przy użyciu Start/StopOperation pomocników. Zrób to z tego samego przepływu sterowania asynchronicznego (kontekstu wykonywania). W ten sposób są one prawidłowo skorelowane.
  • Zatrzymaj element Activity.
  • Ręczne używanie Start/StopOperation danych telemetrycznych lub wywoływanie Track ich.

Typy zależności

Aplikacja Szczegółowe informacje używa typu zależności do dostosowywania środowisk interfejsu użytkownika. W przypadku kolejek rozpoznaje następujące typy DependencyTelemetry , które zwiększają środowisko diagnostyki transakcji:

  • Azure queue dla kolejek usługi Azure Storage
  • Azure Event Hubs dla usługi Azure Event Hubs
  • Azure Service Bus dla usługi Azure Service Bus

Przetwarzanie wsadowe

W przypadku niektórych kolejek można usunąć kolejkę wielu komunikatów z jednym żądaniem. Przetwarzanie takich komunikatów jest prawdopodobnie niezależne i należy do różnych operacji logicznych. Nie można skorelować Dequeue operacji z przetwarzanym konkretnym komunikatem.

Każdy komunikat powinien być przetwarzany we własnym asynchronicznym przepływie sterowania. Aby uzyskać więcej informacji, zobacz sekcję Śledzenie zależności wychodzących.

Długotrwałe zadania w tle

Niektóre aplikacje uruchamiają długotrwałe operacje, które mogą być spowodowane żądaniami użytkowników. Z perspektywy śledzenia/instrumentacji nie różni się ona od instrumentacji żądań lub zależności:

async Task BackgroundTask()
{
    var operation = telemetryClient.StartOperation<DependencyTelemetry>(taskName);
    operation.Telemetry.Type = "Background";
    try
    {
        int progress = 0;
        while (progress < 100)
        {
            // Process the task.
            telemetryClient.TrackTrace($"done {progress++}%");
        }
        // Update status code and success as appropriate.
    }
    catch (Exception e)
    {
        telemetryClient.TrackException(e);
        // Update status code and success as appropriate.
        throw;
    }
    finally
    {
        telemetryClient.StopOperation(operation);
    }
}

W tym przykładzie telemetryClient.StartOperation tworzy DependencyTelemetry i wypełnia kontekst korelacji. Załóżmy, że masz operację nadrzędną, która została utworzona przez przychodzące żądania, które planowały operację. Tak długo, jak BackgroundTask rozpoczyna się w tym samym przepływie sterowania asynchronicznym co żądanie przychodzące, jest skorelowany z tą operacją nadrzędną. BackgroundTask i wszystkie zagnieżdżone elementy telemetrii są automatycznie skorelowane z żądaniem, które je spowodowało, nawet po zakończeniu żądania.

Gdy zadanie rozpoczyna się od wątku w tle, który nie ma żadnej operacji (Activity) skojarzonej z nim, BackgroundTask nie ma żadnego elementu nadrzędnego. Może jednak mieć zagnieżdżone operacje. Wszystkie elementy telemetrii zgłoszone z zadania są skorelowane z utworzonym elementem DependencyTelemetry w programie BackgroundTask.

Śledzenie zależności wychodzących

Możesz śledzić własny rodzaj zależności lub operację, która nie jest obsługiwana przez aplikację Szczegółowe informacje.

Enqueue Metoda w kolejce usługi Service Bus lub w kolejce usługi Storage może służyć jako przykłady takiego śledzenia niestandardowego.

Ogólne podejście do niestandardowego śledzenia zależności polega na następujących celach:

  • Wywołaj metodę TelemetryClient.StartOperation (extension), która wypełnia DependencyTelemetry właściwości wymagane do korelacji i innych właściwości, takich jak start, sygnatura czasowa i czas trwania.
  • Ustaw inne właściwości niestandardowe na DependencyTelemetryobiekcie , takie jak nazwa i dowolny inny kontekst, którego potrzebujesz.
  • Utwórz wywołanie zależności i poczekaj na to.
  • Zatrzymaj operację StopOperation po zakończeniu.
  • Obsługa wyjątków.
public async Task RunMyTaskAsync()
{
    using (var operation = telemetryClient.StartOperation<DependencyTelemetry>("task 1"))
    {
        try 
        {
            var myTask = await StartMyTaskAsync();
            // Update status code and success as appropriate.
        }
        catch(...) 
        {
            // Update status code and success as appropriate.
        }
    }
}

Usuwanie operacji powoduje zatrzymanie operacji, więc można to zrobić zamiast wywoływać StopOperation.

Ostrzeżenie

W niektórych przypadkach nieobsługiwany wyjątek może uniemożliwić finally wywoływanie, więc operacje mogą nie być śledzone.

Przetwarzanie i śledzenie operacji równoległych

Wywołanie StopOperation zatrzymuje tylko uruchomioną operację. Jeśli bieżąca uruchomiona operacja jest niezgodna z bieżącą operacją, którą chcesz zatrzymać, StopOperation nic nie robi. Taka sytuacja może wystąpić, jeśli równolegle uruchomisz wiele operacji w tym samym kontekście wykonywania.

var firstOperation = telemetryClient.StartOperation<DependencyTelemetry>("task 1");
var firstTask = RunMyTaskAsync();

var secondOperation = telemetryClient.StartOperation<DependencyTelemetry>("task 2");
var secondTask = RunMyTaskAsync();

await firstTask;

// FAILURE!!! This will do nothing and will not report telemetry for the first operation
// as currently secondOperation is active.
telemetryClient.StopOperation(firstOperation); 

await secondTask;

Upewnij się, że zawsze wywołujesz StartOperation operację i przetwarzasz operację w tej samej metodzie asynchronicznej , aby odizolować operacje uruchomione równolegle. Jeśli operacja jest synchroniczna (lub nie asynchroniczna), opakuj proces i śledź za pomocą polecenia Task.Run.

public void RunMyTask(string name)
{
    using (var operation = telemetryClient.StartOperation<DependencyTelemetry>(name))
    {
        Process();
        // Update status code and success as appropriate.
    }
}

public async Task RunAllTasks()
{
    var task1 = Task.Run(() => RunMyTask("task 1"));
    var task2 = Task.Run(() => RunMyTask("task 2"));
    
    await Task.WhenAll(task1, task2);
}

Application Szczegółowe informacje operations vs. System.Diagnostics.Activity

System.Diagnostics.Activity reprezentuje kontekst śledzenia rozproszonego i jest używany przez struktury i biblioteki do tworzenia i propagowania kontekstu wewnątrz i poza procesem oraz korelowania elementów telemetrii. Activity współpracuje ze sobą jako mechanizm powiadamiania między strukturą System.Diagnostics.DiagnosticSource /biblioteką w celu powiadamiania o interesujących zdarzeniach, takich jak przychodzące lub wychodzące żądania i wyjątki.

Działania są obywatelami pierwszej klasy w aplikacji Szczegółowe informacje. Automatyczne zależności i zbieranie żądań polegają na nich w dużym stopniu wraz ze zdarzeniami DiagnosticSource . Jeśli utworzono Activity aplikację, nie spowoduje to utworzenia telemetrii Szczegółowe informacje aplikacji. Aplikacja Szczegółowe informacje musi odbierać DiagnosticSource zdarzenia i znać nazwy zdarzeń i ładunki do tłumaczenia Activity na dane telemetryczne.

Każda operacja Szczegółowe informacje aplikacji (żądanie lub zależność) obejmuje .Activity Gdy StartOperation jest wywoływany, tworzy Activity pod spodem. StartOperation to zalecany sposób ręcznego śledzenia telemetrii żądań lub zależności i upewnienia się, że wszystko jest skorelowane.

Następne kroki

  • Poznaj podstawy korelacji telemetrii w usłudze Application Szczegółowe informacje.
  • Sprawdź, jak skorelowane dane zasilają środowisko diagnostyki transakcji i mapę aplikacji.
  • Zobacz model danych dla typów Szczegółowe informacje aplikacji i modelu danych.
  • Zgłaszanie zdarzeń niestandardowych i metryk do usługi Application Szczegółowe informacje.
  • Zapoznaj się ze standardową konfiguracją kolekcji właściwości kontekstu.
  • Zapoznaj się z podręcznikiem użytkownika System.Diagnostics.Activity, aby zobaczyć, jak korelujemy dane telemetryczne.