Verwenden Sie OpenTelemetry mit OTLP und dem Aspire Dashboard

In diesem Artikel erfahren Sie, wie Sie eine .NET Web-API mit OpenTelemetry instrumentieren und ihre Protokolle, Metriken und Ablaufverfolgungen mithilfe von OTLP an das Aspire Dashboard senden. Sie fügen die OpenTelemetry-Pakete hinzu, konfigurieren benutzerdefinierte Metriken und Ablaufverfolgungen, und zeigen die Ergebnisse im Dashboard an.

Das Aspire Dashboard ist ein Standardteil von Aspire, aber es ist auch als eigenständiger Docker-Container verfügbar, der einen OTLP-Endpunkt zum Senden von Telemetrie bereitstellt. Das Dashboard visualisiert Protokolle, Metriken und Ablaufverfolgungen. Die Verwendung des Dashboards auf diese Weise hat keine Abhängigkeit Aspirevon und visualisiert Telemetrie aus jeder App, die Telemetrie mithilfe von OTLP sendet. Es eignet sich gleichermaßen gut für Apps, die in Java, Go oder Python geschrieben wurden, vorausgesetzt, sie können ihre Telemetrie an einen OTLP-Endpunkt senden.

Das Aspire Dashboard erfordert weniger Konfigurationsschritte und weniger Einrichtungsschritte als Open-Source-Lösungen wie Prometheus, Grafana und Jaeger. Im Gegensatz zu diesen Tools ist das Aspire Dashboard jedoch ein Entwicklervisualisierungstool, kein Produktionsüberwachungstool.

1. Erstellen des Projekts

Erstellen Sie ein einfaches Web-API-Projekt, indem Sie die Vorlage ASP.NET Core Empty in Visual Studio oder den folgenden .NET CLI-Befehl verwenden:

dotnet new web

2. Verweisen Sie auf die OpenTelemetry-Pakete

Um die OpenTelemetry-Pakete hinzuzufügen, verwenden Sie die NuGet-Paket-Manager, oder führen Sie die folgenden dotnet add package Befehle aus:

dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package OpenTelemetry.Instrumentation.Http

Fügen Sie alternativ die folgenden PackageReference Elemente direkt zur Projektdatei hinzu:

<ItemGroup>
  <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.19.1" />
  <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.19.1" />
  <PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.19.0" />
  <PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.19.0" />
</ItemGroup>

Hinweis

Da sich die OTel-APIs ständig weiterentwickeln, verwenden Sie die neuesten Versionen.

3. Hinzufügen von Using-Direktiven

Fügen Sie die folgenden using Direktiven am Anfang der Datei hinzu:

using System.Diagnostics;
using System.Diagnostics.Metrics;
using OpenTelemetry.Exporter;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

4. Hinzufügen von Metriken und Aktivitätsdefinitionen

Der folgende Code definiert eine neue Metrik (greetings.count), die zählt, wie oft ein Client die API aufruft, und eine neue Aktivitätsquelle (Otel.Example). Fügen Sie diesen Code vor builder.Build:

// Custom metrics for the application
var greeterMeter = new Meter("OTel.Example", "1.0.0");
var countGreetings = greeterMeter.CreateCounter<int>("greetings.count", description: "Counts the number of greetings");

// Custom ActivitySource for the application
var greeterActivitySource = new ActivitySource("OTel.Example");

5. Konfigurieren von OpenTelemetry mit den richtigen Anbietern

Fügen Sie den folgende Code vor builder.Build ein:

// Configure the shared OTLP connection used by logs, metrics, and traces.
var otlpEndpoint = new Uri(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]!);
Action<OtlpExporterOptions> configureOtlp = options =>
{
    options.Endpoint = otlpEndpoint;
    options.Protocol = OtlpExportProtocol.Grpc;
    options.Headers = builder.Configuration["OTEL_EXPORTER_OTLP_HEADERS"]; // To secure endpoint (not in this example)
};

// Setup logging to be exported via OpenTelemetry
builder.Logging.AddOpenTelemetry(logging =>
{
    logging.IncludeFormattedMessage = true;
    logging.IncludeScopes = true;
    logging.AddOtlpExporter(configureOtlp);
});

var otel = builder.Services.AddOpenTelemetry();

// Identify this application as a single service in the Aspire dashboard.
otel.ConfigureResource(resource => resource.AddService(builder.Configuration["OTEL_SERVICE_NAME"]!));

// Add Metrics for ASP.NET Core and our custom metrics and export via OTLP
otel.WithMetrics(metrics =>
{
    // Metrics provider from OpenTelemetry
    metrics.AddAspNetCoreInstrumentation();

    // Our custom metrics
    metrics.AddMeter(greeterMeter.Name);

    // Metrics provided by ASP.NET Core in .NET
    metrics.AddMeter("Microsoft.AspNetCore.Hosting");
    metrics.AddMeter("Microsoft.AspNetCore.Server.Kestrel");

    // Export the metrics via OTLP
    metrics.AddOtlpExporter(configureOtlp);
});

// Add Tracing for ASP.NET Core and our custom ActivitySource and export via OTLP
otel.WithTracing(tracing =>
{
    tracing.AddAspNetCoreInstrumentation();
    tracing.AddHttpClientInstrumentation();
    tracing.AddSource(greeterActivitySource.Name);
    tracing.AddOtlpExporter(configureOtlp);
});

Dieser Code richtet OpenTelemetry mit den verschiedenen Telemetriequellen ein:

  • Es fügt ILogger einen OTel-Provider hinzu, um Protokolleinträge zu sammeln.
  • Es richtet Metriken ein, registriert Instrumentierungsanbieter und Meter für ASP.NET und den benutzerdefinierten Zähler.
  • Es richtet die Nachverfolgung ein, registriert Instrumentierungsanbieter und das benutzerdefinierte ActivitySource.

Anschließend wird der OTLP-Exporter mithilfe von Umgebungsvariablen für seine Konfiguration registriert.

6. Konfigurieren von OTLP-Einstellungen

Sie können den OTLP-Exporter über APIs in Code, Umgebungsvariablen oder Anwendungskonfiguration konfigurieren. Fügen Sie in diesem Beispiel die OTLP-Einstellungen auf der obersten Ebene von appsettings.Development.json nach dem Abschnitt Logging hinzu:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317",
  "OTEL_SERVICE_NAME": "OTLP-Example"
}

Fügen Sie weitere Einstellungen für den .NET OTLP-Exporter oder allgemeine OTel-Einstellungen hinzu, zOTEL_RESOURCE_ATTRIBUTES. B. zum Definieren von Ressourcenattributen.

Hinweis

ASP.NET Core lädt sowohl appsettings.Development.json als auch appsettings.json. Einstellungen in appsettings.Development.json überschreiben doppelte Einstellungen in appsettings.json, wenn Sie die App in der Entwicklungsumgebung ausführen.

7. Erstellen eines API-Endpunkts

Fügen Sie den folgenden Code zwischen builder.Build und app.Run():

app.MapGet("/", SendGreeting);

Fügen Sie am Ende der Datei die folgende Funktion hinzu:

async Task<string> SendGreeting(ILogger<Program> logger)
{
    // Create a new Activity scoped to the method
    using var activity = greeterActivitySource.StartActivity("GreeterActivity");

    // Log a message
    logger.LogInformation("Sending greeting");

    // Increment the custom counter
    countGreetings.Add(1);

    // Add a tag to the Activity
    activity?.SetTag("greeting", "Hello World!");

    return "Hello World!";
}

Hinweis

Die Endpunktdefinition verwendet nichts spezifisches für OpenTelemetry. Zur Beobachtbarkeit werden die .NET-APIs verwendet.

8. Starten des Dashboardcontainers Aspire

Verwenden Sie docker, um den Dashboard-Container herunterzuladen und auszuführen.

docker run --rm -it `
-p 18888:18888 `
-p 4317:18889 `
--name aspire-dashboard `
mcr.microsoft.com/dotnet/aspire-dashboard:latest

Auf dem Dashboard angezeigte Daten können vertraulich sein. Standardmäßig erfordert das Dashboard ein Authentifizierungstoken für die Anmeldung. Der Container zeigt dieses Token in seiner Ausgabe an.

Aspire Dashboard

Kopieren Sie die URL, ersetzen Sie 0.0.0.0 durch localhost, z. B. http://localhost:18888/login?t=123456780abcdef123456780, und öffnen Sie sie in Ihrem Browser. Oder fügen Sie den Schlüssel nach /login?t= in den Anmeldedialog ein. Das Token ändert sich jedes Mal, wenn Sie den Container starten.

9. Ausführen des Projekts

Führen Sie das Projekt mit dotnet run aus. Die Konsolenausgabe zeigt die URLs an, auf die die App lauscht, z. B.:

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5086

Verwenden Sie den port, der in Ihrer eigenen Konsolenausgabe angezeigt wird, da er sich möglicherweise von den Beispielen in diesem Artikel unterscheidet. Verwenden Sie einen Browser oder eine Curl, um auf die API für diesen Port zuzugreifen:

curl -k http://localhost:5086

Jedes Mal, wenn Sie die Seite anfordern, erhöht sich die Anzahl der Begrüßungen.

9.1 Protokollausgabe

Der Code protokolliert Anweisungen mithilfe von ILogger. Standardmäßig aktiviert .NET den Konsolenanbieter, der die Ausgabe an die Konsole leitet.

Sie können Protokolle aus .NET auf verschiedene Weise exportieren:

  • Containersysteme wie Kubernetes leiten die Ausgaben von stdout und stderr in Protokolldateien um.
  • Verwenden Sie Protokollierungsbibliotheken, die in ILoggerintegriert sind , z. B. Serilog und NLog.
  • Verwenden Sie Protokollierungsanbieter für OTel, z. B. OTLP. Der Protokollierungsbereich des Codes in Schritt 5 fügt den OTel-Anbieter hinzu.

Das Dashboard zeigt Protokolle als strukturierte Protokolle an. Alle Eigenschaften, die Sie in der Protokollnachricht festlegen, werden zu Feldern im Protokolldatensatz.

Protokolle auf dem eigenständigen Dashboard

9.2 Metrikenansicht

Das Aspire Dashboard zeigt Metriken pro Ressource an. Eine Ressource ist der OTel-Begriff für eine Telemetriequelle, z. B. einen Prozess. Wenn Sie eine Ressource auswählen, listet das Dashboard jede Metrik auf, die die Ressource an den OTLP-Endpunkt gesendet hat. Die Liste der Metriken ist dynamisch und aktualisiert sich, wenn das Dashboard neue Metriken erhält.

Metriken auf dem eigenständigen Dashboard

Die Metrikansicht hängt vom Typ der metriken ab, die Sie verwenden:

  • Das Dashboard zeigt Zähler direkt an.
  • Bei Histogrammen, die pro Anfrage einen Wert erfassen, z. B. eine Zeitspanne oder die pro Anfrage gesendeten Bytes, sammelt das Dashboard die Werte in einer Reihe von Klassen und stellt die P50-, P90- und P99-Perzentile grafisch dar. Histogrammergebnisse können Exemplare enthalten, also einzelne Datenpunkte zusammen mit der Trace-/Span-ID für diese Anfrage. Das Dashboard zeigt diese als Punkte im Diagramm an. Wählen Sie einen Eintrag aus, um zur entsprechenden Trace zu wechseln, damit Sie sehen können, wodurch dieser Wert verursacht wurde. Mit diesem Feature können Sie Ausreißer diagnostizieren.
  • Metriken können Dimensionen enthalten, bei denen es sich um Schlüssel-Wert-Paare handelt, die einzelnen Werten zugeordnet sind. Das Dashboard aggregiert Werte pro Dimension. Verwenden Sie die Dropdowns in der Ansicht, um Ergebnisse anhand bestimmter Dimensionen zu filtern, z. B. nur nach GETAnfragen oder nach einer bestimmten URL-Route in ASP.NET.

9.3 Nachverfolgungsansicht

Die Ablaufverfolgungsansicht listet Ablaufverfolgungen auf. Jeder Trace ist eine Menge von Aktivitäten, die dieselbe Trace-ID haben. Spans verfolgen die Arbeit nach, und jeder Span stellt eine Arbeitseinheit dar. Die Verarbeitung einer ASP.NET Anforderung erstellt eine Spanne. Das Erstellen einer HttpClient-Anforderung ist ein Span. Indem Sie den jeweiligen übergeordneten Span verfolgen, erstellen Sie eine Hierarchie von Spans, die Sie visualisieren können. Wenn Sie Spans aus jeder Ressource (jedem Prozess) erfassen, können Sie Arbeitsabläufe über eine Reihe von Diensten hinweg nachverfolgen. HTTP-Anfragen enthalten einen Header, der die Trace-ID und die Parent-Span-ID an den nächsten Dienst übergibt. Jede Ressource muss Telemetrie sammeln und an denselben Sammler senden, der dann eine Hierarchie der Spannen aggregiert und darstellt.

Spuren im eigenständigen Dashboard

Das Dashboard zeigt eine Liste der Spuren mit Übersichtsinfos an. Immer wenn das Dashboard Spans mit einer neuen Trace-ID erkennt, fügt es der Tabelle eine Zeile hinzu. Wählen Sie Ansicht aus, um alle Spans in der Ablaufverfolgung anzuzeigen.

span-Elemente auf dem eigenständigen Dashboard

Wählen Sie einen Span aus, um dessen Details anzuzeigen, einschließlich aller Eigenschaften des Span, wie etwa des Tags greeting, das Sie in Schritt 7 festgelegt haben.