Freigeben über


Aktivieren von Browsertelemetrie

Das .NET.NET Aspire-Dashboard kann so konfiguriert werden, dass Telemetrie empfangen wird, die von Browser-Apps gesendet wird. Dieses Feature ist nützlich, um clientseitige Leistung und Benutzerinteraktionen zu überwachen. Browsertelemetrie erfordert zusätzliche Dashboardkonfiguration und dass das JavaScript OTEL SDK den Browser-Apps hinzugefügt wird.

In diesem Artikel wird erläutert, wie Sie Browsertelemetrie im .NET.NET Aspire-Dashboard aktivieren.

Dashboard-Konfiguration

Für die Browsertelemetrie ist das Dashboard erforderlich, um diese Features zu aktivieren:

  • OTLP-HTTP-Endpunkt. Dieser Endpunkt wird vom Dashboard verwendet, um Telemetrie von Browser-Apps zu empfangen.
  • Ursprungsübergreifende Ressourcenfreigabe (CORS). CORS ermöglicht Browser-Apps das Senden von Anforderungen an das Dashboard.

OTLP-Konfiguration

Das .NET-.NET Aspire-Dashboard empfängt Telemetrie über OTLP-Endpunkte. HTTP-OTLP-Endpunkte und gRPC-OTLP-Endpunkte werden vom Dashboard unterstützt. Browser-Apps müssen HTTP OLTP verwenden, um Telemetrie an das Dashboard zu senden, da Browser-Apps gRPC nicht unterstützen.

Um die gPRC- oder HTTP-Endpunkte zu konfigurieren, geben Sie die folgenden Umgebungsvariablen an:

  • DOTNET_DASHBOARD_OTLP_ENDPOINT_URL: Der gRPC-Endpunkt, mit dem das Dashboard eine Verbindung für seine Daten herstellt.
  • DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL: Der HTTP-Endpunkt, mit dem das Dashboard eine Verbindung für seine Daten herstellt.

Die Konfiguration des HTTP OTLP-Endpunkts hängt davon ab, ob das Dashboard vom App-Host gestartet oder eigenständig ausgeführt wird.

OTLP-HTTP mit dem App-Host konfigurieren

Wenn das Dashboard und Ihre App vom App-Host gestartet werden, werden die OTLP-Dashboard-Endpunkte in der launchSettings.json-Datei des App-Hosts konfiguriert.

Betrachten Sie die folgende Beispieldatei JSON:

{
  "$schema": "http://json.schemastore.org/launchsettings.json",
  "profiles": {
    "https": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "https://localhost:15887;http://localhost:15888",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "DOTNET_ENVIRONMENT": "Development",
        "DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL": "https://localhost:16175",
        "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:17037",
        "DOTNET_ASPIRE_SHOW_DASHBOARD_RESOURCES": "true"
      }
    },
    "http": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "http://localhost:15888",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "DOTNET_ENVIRONMENT": "Development",
        "DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL": "http://localhost:16175",
        "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:17037",
        "DOTNET_ASPIRE_SHOW_DASHBOARD_RESOURCES": "true",
        "ASPIRE_ALLOW_UNSECURED_TRANSPORT": "true"
      }
    },
    "generate-manifest": {
      "commandName": "Project",
      "launchBrowser": true,
      "dotnetRunMessages": true,
      "commandLineArgs": "--publisher manifest --output-path aspire-manifest.json",
      "applicationUrl": "http://localhost:15888",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "DOTNET_ENVIRONMENT": "Development"
      }
    }
  }
}

Die vorherigen Starteinstellungen JSON Datei konfiguriert alle Profile so, dass sie die DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL Umgebungsvariable enthalten.

OTLP HTTP mit einem eigenständigen Dashboard konfigurieren

Wenn das Dashboard eigenständig verwendet wird, ohne den Rest von .NET.NET Aspire, ist der OTLP-HTTP-Endpunkt standardmäßig für den Port 18890aktiviert. Der Port muss jedoch zugeordnet werden, wenn der Dashboardcontainer gestartet wird:

docker run --rm -it -d \
    -p 18888:18888 \
    -p 4317:18889 \
    -p 4318:18890 \
    --name aspire-dashboard \
    mcr.microsoft.com/dotnet/aspire-dashboard:9.0

Der vorangegangene Befehl führt den Dashboard-Container aus und ordnet gRPC OTLP auf Port 4317 und HTTP OTLP auf Port 4318zu.

CORS-Konfiguration

Browser-Apps sind standardmäßig daran eingeschränkt, domänenübergreifende API-Aufrufe durchzuführen. Dies wirkt sich auf das Senden von Telemetrie an das Dashboard aus, da sich das Dashboard und die Browser-App immer auf unterschiedlichen Domänen befinden. Durch das Konfigurieren von CORS im .NET.NET Aspire-Dashboard wird die Einschränkung entfernt.

Wenn das Dashboard und Ihre App vom App-Host gestartet werden, ist keine CORS-Konfiguration erforderlich. .NET .NET Aspire konfiguriert das Dashboard automatisch so, dass alle Quellen zulässig sind.

Wenn das Dashboard eigenständig verwendet wird, muss CORS manuell konfiguriert werden. Die Domäne, die zum Anzeigen der Browser-App verwendet wird, muss als zulässiger Ursprung konfiguriert werden, indem die Umgebungsvariable DASHBOARD__OTLP__CORS__ALLOWEDORIGINS angegeben wird, wenn der Dashboardcontainer gestartet wird:

docker run --rm -it -d \
    -p 18888:18888 \
    -p 4317:18889 \
    -p 4318:18890 \
    -e DASHBOARD__OTLP__CORS__ALLOWEDORIGINS=https://localhost:8080 \
    --name aspire-dashboard \
    mcr.microsoft.com/dotnet/aspire-dashboard:9.0

Der obige Befehl führt den Dashboardcontainer aus und konfiguriert https://localhost:8080 als zulässigen Ursprung. Dies bedeutet, dass eine Browser-App, auf die mithilfe von https://localhost:8080 zugegriffen wird, über die Berechtigung zum Senden der Dashboard-Telemetrie verfügt.

Mehrere Ursprünge können mit einem durch Kommas getrennten Wert zulässig sein. Oder alle Ursprünge können mit dem *-Wildcard zulässig sein. Beispiel: DASHBOARD__OTLP__CORS__ALLOWEDORIGINS=*.

Weitere Informationen finden Sie unter .NET.NET Aspire Dashboard-Konfiguration: OTLP CORS.

OTLP-Endpunktsicherheit

Dashboard-OTLP-Endpunkte können mit API-Schlüsselauthentifizierung gesichert werden. Wenn aktiviert, müssen HTTP-OTLP-Anforderungen an das Dashboard den API-Schlüssel als Header x-otlp-api-key enthalten. Standardmäßig wird bei jeder Ausführung des Dashboards ein neuer API-Schlüssel generiert.

Die API-Schlüsselauthentifizierung wird automatisch aktiviert, wenn das Dashboard vom App-Host ausgeführt wird. Die Dashboardauthentifizierung kann durch Festlegen von DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS auf true in der launchSettings.json-Datei des App-Hosts deaktiviert werden.

OTLP-Endpunkte sind standardmäßig im eigenständigen Dashboard ungesichert.

Browser-App-Konfiguration

Eine Browser-App verwendet das JavaScript OTEL SDK, um Telemetrie an das Dashboard zu senden. Das erfolgreiche Senden von Telemetrie an das Dashboard erfordert, dass das SDK ordnungsgemäß konfiguriert ist.

OTLP-Exporter

OTLP-Exporteure müssen in der Browser-App enthalten sein und mit dem SDK konfiguriert werden. Der Export von verteiltem Tracing mit OTLP erfolgt über das @opentelemetry/exporter-trace-otlp-proto-Paket.

Wenn OTLP dem SDK hinzugefügt wird, müssen OTLP-Optionen angegeben werden. OTLP-Optionen umfassen:

  • url: Die Adresse, an die HTTP OTLP-Anforderungen gesendet werden. Die Adresse sollte der HTTP-OTLP-Endpunkt des Dashboards und der Pfad zur OTLP-HTTP-API sein. Beispiel: https://localhost:4318/v1/traces für den OTLP-Ablaufverfolgungsexporteur. Wenn die Browser-App vom App-Host gestartet wird, ist der HTTP-OTLP-Endpunkt über die umgebungsvariable OTEL_EXPORTER_OTLP_ENDPOINT verfügbar.

  • headers: Die kopfzeilen, die mit Anforderungen gesendet wurden. Wenn die OTLP-Endpunkt-API-Schlüsselauthentifizierung aktiviert ist, muss der x-otlp-api-key-Header mit OTLP-Anforderungen gesendet werden. Wenn die Browser-App vom App-Host gestartet wird, ist der API-Schlüssel über die umgebungsvariable OTEL_EXPORTER_OTLP_HEADERS verfügbar.

Browsermetadaten

Wenn eine Browser-App so konfiguriert ist, dass verteilte Traces gesammelt werden, kann die Browser-App den Trace Parent eines Browsers mithilfe des meta-Elements im HTML-Code setzen. Der Wert des name="traceparent" Meta-Elements sollte der aktuellen Ablaufverfolgung entsprechen.

In einer .NET-App wird der übergeordnete Wert der Ablaufverfolgung wahrscheinlich vom Activity.Current zugewiesen und deren Activity.Id Wert als contentübergeben. Betrachten Sie beispielsweise den folgenden Razor-Code:

<head>
    @if (Activity.Current is { } currentActivity)
    {
        <meta name="traceparent" content="@currentActivity.Id" />
    }
    <!-- Other elements omitted for brevity... -->
</head>

Der vorherige Code legt das Metadaten-Element traceparent auf die ID der aktuellen Aktivität fest.

Beispielcode für Browsertelemetrie

Der folgende JavaScript-Code veranschaulicht die Initialisierung des OpenTelemetry JavaScript SDK und das Senden von Telemetriedaten an das Dashboard:

import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { Resource } from '@opentelemetry/resources';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
import { ZoneContextManager } from '@opentelemetry/context-zone';

export function initializeTelemetry(otlpUrl, headers, resourceAttributes) {
    const otlpOptions = {
        url: `${otlpUrl}/v1/traces`,
        headers: parseDelimitedValues(headers)
    };

    const attributes = parseDelimitedValues(resourceAttributes);
    attributes[SemanticResourceAttributes.SERVICE_NAME] = 'browser';

    const provider = new WebTracerProvider({
        resource: new Resource(attributes),
    });
    provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
    provider.addSpanProcessor(new SimpleSpanProcessor(new OTLPTraceExporter(otlpOptions)));

    provider.register({
        // Prefer ZoneContextManager: supports asynchronous operations
        contextManager: new ZoneContextManager(),
    });

    // Registering instrumentations
    registerInstrumentations({
        instrumentations: [new DocumentLoadInstrumentation()],
    });
}

function parseDelimitedValues(s) {
    const headers = s.split(','); // Split by comma
    const result = {};

    headers.forEach(header => {
        const [key, value] = header.split('='); // Split by equal sign
        result[key.trim()] = value.trim(); // Add to the object, trimming spaces
    });

    return result;
}

Der vorangehende JavaScript-Code definiert eine initializeTelemetry-Funktion, die die OTLP-Endpunkt-URL, die Header und die Ressourcenattribute erwartet. Diese Parameter werden von der verbrauchenden Browser-App bereitgestellt, die sie aus den vom App-Host festgelegten Umgebungsvariablen abruft. Beachten Sie den folgenden Razor-Code:

@using System.Diagnostics
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - BrowserTelemetry</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />

    @if (Activity.Current is { } currentActivity)
    {
        <meta name="traceparent" content="@currentActivity.Id" />
    }
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">BrowserTelemetry</a>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>
    @await RenderSectionAsync("Scripts", required: false)
    <script src="scripts/bundle.js"></script>
    @if (Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT") is { Length: > 0 } endpointUrl)
    {
        var headers = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_HEADERS");
        var attributes = Environment.GetEnvironmentVariable("OTEL_RESOURCE_ATTRIBUTES");
        <script>
            BrowserTelemetry.initializeTelemetry('@endpointUrl', '@headers', '@attributes');
        </script>
    }
</body>
</html>

Trinkgeld

Die Bündelung und Minimierung des JavaScript-Codes geht über den Rahmen dieses Artikels hinaus.

Das vollständige Beispiel, um das JavaScript OTEL-SDK so zu konfigurieren, dass Telemetrie an das Dashboard gesendet wird, finden Sie im Browser-Telemetrie-Beispiel.

Siehe auch