Aktivera OpenTelemetry-distribuerad spårning med Durable Task Scheduler

Distribuerad spårning ger fullständig insyn i orkestreringskörningen från början till slut. När du aktiverar OpenTelemetry med Durable Task Scheduler skapar varje orkestrering, aktivitet och underorkestrering länkade intervall som visar tidsintervall, ordning och fel i hela arbetsflödet. Du kan exportera dessa spårningar till valfri OpenTelemetry-kompatibel serverdel, till exempel Azure Monitor Application Insights, Jaeger eller Zipkin.

Durable Functions och fristående Durable Task SDK:er stöder båda OpenTelemetry-distribuerad spårning när du använder Durable Task Scheduler som serverdel.

Så här fungerar det

Durable Task SDK:er instrumenterar automatiskt orkestreringar och aktiviteter med OpenTelemetry-intervall. SDK skapar ett överordnat spann för varje orkestrering och underordnade intervall för varje aktivitetsanrop, underorkestrering och timer. Spårningskontexten sprids automatiskt över alla dessa åtgärder, så du får en enda, korrelerad spårning för hela arbetsflödet.

Det resulterande spårningsträdet ser ut så här:

create_orchestration (client)
  └─ orchestration (server)
       ├─ activity:Step1
       ├─ activity:Step2
       └─ activity:Step3

Du behöver inte lägga till anpassad instrumentation i orkestrerings- eller aktivitetskoden. Registrera aktivitetskällan Microsoft.DurableTask med din OpenTelemetry-konfiguration och SDK hanterar resten.

Förutsättningar

  • Ett Azure Functions projekt med tillägget Durable Functions version 2.13.0 eller senare.
  • Durable Task Scheduler konfigurerad som lagringsserverdel för funktionsappen.
  • En OpenTelemetry-kompatibel serverdel för visning av spårningar (Application Insights, Jaeger eller en annan OTLP-insamlare).
  • .NET 8 SDK eller senare.
  • De Microsoft.DurableTask.Worker.AzureManaged och Microsoft.DurableTask.Client.AzureManaged NuGet-paketen.
  • NuGet-paketen OpenTelemetry, OpenTelemetry.Extensions.Hosting och OpenTelemetry.Exporter.OpenTelemetryProtocol.
  • En OpenTelemetry-kompatibel serverdel för visning av spårningar, till exempel Application Insights för produktion eller Jaeger för lokal utveckling.

Aktivera distribuerad spårning

Om du vill aktivera distribuerad spårning i Durable Functions uppdaterar du din host.json och konfigurerar en OpenTelemetry-kompatibel telemetriserverdel.

Uppdatera host.json

Lägg till avsnittet tracing under durableTask i dinhost.json-fil :

{
  "version": "2.0",
  "extensions": {
    "durableTask": {
      "tracing": {
        "DistributedTracingEnabled": true,
        "Version": "V2"
      }
    }
  }
}

Konfigurera Application Insights

APPLICATIONINSIGHTS_CONNECTION_STRING Ange miljövariabeln i funktionsappen.

För lokal utveckling, lägg till det i local.settings.json:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
    "APPLICATIONINSIGHTS_CONNECTION_STRING": "<your-connection-string>"
  }
}

För Azure värdbaserade appar lägger du till den som en programinställning under Konfiguration i Azure-portalen.

Anmärkning

Om du tidigare använde APPINSIGHTS_INSTRUMENTATIONKEYväxlar du till APPLICATIONINSIGHTS_CONNECTION_STRING för de senaste funktionerna.

Minska telemetribruller

Om du vill förhindra att Application Insights samplar spårningsdata undantar du Request från samplingsregler i host.json:

{
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  }
}

Registrera aktivitetskällan Microsoft.DurableTask med din OpenTelemetry-konfiguration. Durable Task SDK skapar automatiskt intervall för orkestreringar och aktiviteter när du registrerar den här källan.

Lägg till OpenTelemetry-spårning med aktivitetskällan Durable Task i din arbetstagares Program.cs:

using Microsoft.DurableTask;
using Microsoft.DurableTask.Worker;
using Microsoft.DurableTask.Worker.AzureManaged;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

var builder = Host.CreateApplicationBuilder(args);

// Configure OpenTelemetry tracing
builder.Services.AddOpenTelemetry()
    .ConfigureResource(resource => resource.AddService("durable-worker"))
    .WithTracing(tracing =>
    {
        tracing
            .AddSource("Microsoft.DurableTask")
            .AddOtlpExporter(opts =>
            {
                opts.Endpoint = new Uri(
                    Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT")
                    ?? "http://localhost:4317");
            });
    });

// Build connection string from environment variables
string endpoint = Environment.GetEnvironmentVariable("ENDPOINT") ?? "http://localhost:8080";
string taskHub = Environment.GetEnvironmentVariable("TASKHUB") ?? "default";
string connectionString = endpoint.Contains("localhost")
    ? $"Endpoint={endpoint};TaskHub={taskHub};Authentication=None"
    : $"Endpoint={endpoint};TaskHub={taskHub};Authentication=DefaultAzure";

// Configure Durable Task worker
builder.Services.AddDurableTaskWorker()
    .AddTasks(tasks =>
    {
        tasks.AddOrchestratorFunc<string, string>(
            "OrderProcessingOrchestration", async (ctx, input) =>
        {
            var validated = await ctx.CallActivityAsync<string>("ValidateOrder", input);
            var payment = await ctx.CallActivityAsync<string>("ProcessPayment", validated);
            var shipment = await ctx.CallActivityAsync<string>("ShipOrder", payment);
            var result = await ctx.CallActivityAsync<string>("SendNotification", shipment);
            return result;
        });

        tasks.AddActivityFunc<string, string>("ValidateOrder", (ctx, input) =>
            Task.FromResult($"Validated({input})"));
        tasks.AddActivityFunc<string, string>("ProcessPayment", (ctx, input) =>
            Task.FromResult($"Paid({input})"));
        tasks.AddActivityFunc<string, string>("ShipOrder", (ctx, input) =>
            Task.FromResult($"Shipped({input})"));
        tasks.AddActivityFunc<string, string>("SendNotification", (ctx, input) =>
            Task.FromResult($"Notified({input})"));
    })
    .UseDurableTaskScheduler(connectionString);

var host = builder.Build();
await host.RunAsync();

Nyckelraden är .AddSource("Microsoft.DurableTask"), som instruerar OpenTelemetry att samla in intervall som Durable Task SDK genererar.

Konfigurera OTLP-slutpunkten

Kodfragmenten ovan refererar OTEL_EXPORTER_OTLP_ENDPOINT till miljövariabeln för att ange målet för spårningsdata. Ange den här variabeln baserat på serverdelen:

Backend Slutpunktsvärde Protokoll
Jaeger (lokal) http://localhost:4317 gRPC
Jaeger (lokal, HTTP) http://localhost:4318 HTTP/protobuf
OpenTelemetry Collector http://<collector-host>:4317 gRPC
Azure Monitor (via OTLP) Använd Azure Monitor-exportören i stället Inte tillämpligt

För lokal utveckling med Jaeger fungerar standardvärdet http://localhost:4317 när Jaeger körs med OTLP gRPC aktiverat (port 4317). JavaScript SDK:n använder HTTP/protobuf som standard, så den är inriktad på port 4318 med /v1/traces som sökväg.

Visa spårningar lokalt med Jaeger-användargränssnittet

För lokal utveckling använder du Durable Task Scheduler-emulatorn med Jaeger för att visa spårningar. Använd en docker-compose.yml för att starta båda tjänsterna:

services:
  dts-emulator:
    image: mcr.microsoft.com/dts/dts-emulator:latest
    ports:
      - "8080:8080"  # gRPC
      - "8082:8082"  # Dashboard
  jaeger:
    image: jaegertracing/jaeger:latest
    ports:
      - "16686:16686"  # Jaeger UI
      - "4317:4317"    # OTLP gRPC
      - "4318:4318"    # OTLP HTTP

Starta infrastrukturen:

docker compose up -d

När du har kört programmet öppnar du Jaeger-användargränssnittet på http://localhost:16686 och söker efter tjänstnamnet (till exempel durable-worker) för att visa spårningar.

För lokal utveckling med Durable Functions skickas distribuerade spårningsdata som standard till Application Insights. Om du vill visa spårningar lokalt utan att distribuera kan du lägga till en OTLP-exportör tillsammans med Application Insights i funktionsappens Program.cs:

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing =>
    {
        tracing
            .AddSource("Microsoft.DurableTask")
            .AddOtlpExporter(opts =>
            {
                opts.Endpoint = new Uri("http://localhost:4317");
            });
    });

Kör sedan Jaeger lokalt med docker run -d -p 16686:16686 -p 4317:4317 jaegertracing/jaeger:latest och öppna Jaeger-användargränssnittet på http://localhost:16686.

Visa spårningar i Application Insights

För produktionsarbetsbelastningar är Application Insights den rekommenderade telemetriserverdelen.

När DistributedTracingEnabled har angetts till true med Version inställt på V2 i host.json genererar din Durable Functions app korrelerade intervall till Application Insights. Så här visar du den fullständiga orkestreringsspårningen i Azure-portalen:

  1. Gå till din Application Insights-resurs i Azure-portalen.
  2. Öppna Transaktionssökning och sök efter orkestreringen efter namn eller instans-ID.
  3. Välj en spårning för att visa transaktionen från slutpunkt till slutpunkt med alla korrelerade intervall.

Spårningen visar orkestreringen som ett överordnat spann med underordnade spann för varje aktivitetsanrop, suborkestrering och timerväntan. Följande mönster skapar distinkta spårningsformer:

Mönster Spårform
Funktionslänkning Sekventiella aktiviteter ligger kapslade under orkestratorintervallet.
Utfan/inflöde Parallell aktivitet sträcker sig överlappande i tid.
Mänsklig interaktion Ett Orchestrator-Span med en lång väntan på en extern händelse.
Monitor Återkommande aktiviteter med tidsinställda pauser mellan iterationer.

Konfigurera OTLP-exportören för att skicka spårningar till Application Insights med hjälp av Azure Monitor OpenTelemetry-exportör eller exportera via OTLP till en OpenTelemetry Collector som vidarebefordras till Application Insights.

Installera nuget-paketet Azure.Monitor.OpenTelemetry.Exporter och ersätt OTLP-exportören med:

builder.Services.AddOpenTelemetry()
    .ConfigureResource(resource => resource.AddService("durable-worker"))
    .WithTracing(tracing =>
    {
        tracing
            .AddSource("Microsoft.DurableTask")
            .AddAzureMonitorTraceExporter(opts =>
            {
                opts.ConnectionString = Environment.GetEnvironmentVariable(
                    "APPLICATIONINSIGHTS_CONNECTION_STRING");
            });
    });

Vad spårningsdata visar

Spårningsdata som skapas av SDK:erna för durable task innehåller:

Intervalltyp Beskrivning
create_orchestration Det intervall på klientsidan som genereras när du schemalägger en ny orkestrering
orchestration Orkestreringsintervallet på serversidan som omfattar hela exekveringslivscykeln
activity:<name> Ett spann för varje aktivitetsanrop som visar tids- och resultat
sub_orchestration:<name> Ett intervall för varje underorkestreringsanrop
timer Ett intervall för varaktiga väntetider för timer

Varje intervall innehåller attribut som durabletask.type, durabletask.task.name, durabletask.task.instance_idoch durabletask.task.task_id. Misslyckade aktiviteter och orkestreringar innehåller felinformation i intervallets status och händelser.

Felsökning

Problematik Lösning
Inga spårningar visas Kontrollera att aktivitetskällan Microsoft.DurableTask är registrerad och att exportörens slutpunkt kan nås.
Spårningar är ofullständiga Kontrollera att OpenTelemetry SDK initieras före Durable Task SDK (särskilt i JavaScript/TypeScript).
Saknade intervall i Application Insights Inaktivera eller justera samplingsinställningarna för att förhindra att spårningsdata tas bort.
Spårningar korrelerar inte Kontrollera att du använder Durable Task Scheduler som serverdel. Spårningskontextspridning kräver schemaläggaren.

Exempelkod