Sdílet prostřednictvím


Povolení telemetrie prohlížeče

Řídicí panel .NET.NET Aspire lze nakonfigurovat tak, aby přijímal telemetrická data odesílaná z aplikací prohlížeče. Tato funkce je užitečná pro monitorování výkonu na straně clienta interakcí uživatelů. Telemetrie prohlížeče vyžaduje další konfiguraci řídicího panelu a že se do aplikací prohlížeče přidá sada JavaScript OTEL SDK.

Tento článek popisuje, jak povolit telemetrii prohlížeče na řídicím panelu .NET.NET Aspire.

Konfigurace řídicího panelu

Telemetrie prohlížeče vyžaduje, aby řídicí panel povolil tyto funkce:

  • Koncový bod HTTP protokolu OTLP. Tento koncový bod používá řídicí panel k příjmu telemetrie z aplikací prohlížeče.
  • Sdílení prostředků mezi zdroji (CORS). CORS umožňuje aplikacím v prohlížeči provádět žádosti na řídicí panel.

Konfigurace OTLP

Řídicí panel .NET.NET Aspire přijímá telemetrii prostřednictvím koncových bodů OTLP. HTTP OTLP koncové body a gRPC OTLP koncové body jsou podporovány řídicím panelem. Aplikace prohlížeče musí k odesílání telemetrických dat na řídicí panel používat protokol HTTP OLTP, protože aplikace prohlížeče nepodporují gRPC.

Pokud chcete nakonfigurovat koncové body gPRC nebo HTTP, zadejte následující proměnné prostředí:

  • DOTNET_DASHBOARD_OTLP_ENDPOINT_URL: Koncový bod gRPC, ke kterému se řídicí panel připojuje pro svá data.
  • DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL: Koncový bod HTTP, ke kterému se řídicí panel připojuje pro svá data.

Konfigurace koncového bodu HTTP OTLP závisí na tom, jestli je řídicí panel spuštěný hostitelem aplikace nebo jestli je spuštěný samostatně.

Konfigurace protokolu HTTP OTLP pomocí hostitele aplikace

Pokud řídicí panel a vaši aplikaci spustí hostitel aplikace, OTLP koncové body řídicího panelu se konfigurují v hostiteli aplikace v souboru "launchSettings" ,json,.

Podívejte se na následující příklad JSON souboru:

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

Předchozí nastavení spuštění JSON soubor nakonfiguruje všechny profily tak, aby zahrnovaly proměnnou prostředí DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL.

Konfigurace protokolu HTTP OTLP pomocí samostatného řídicího panelu

Pokud se řídicí panel používá samostatně, bez rest z .NET Aspire, je koncový bod HTTP OTLP ve výchozím nastavení povolen na portu 18890. Port se ale musí namapovat při spuštění kontejneru řídicího panelu:

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

Předchozí příkaz spustí kontejner řídicího panelu a mapuje gRPC OTLP na port 4317 a HTTP OTLP na port 4318.

Konfigurace CORS

Ve výchozím nastavení jsou aplikace prohlížeče omezené na volání rozhraní API napříč doménou. To má vliv na odesílání telemetrie na řídicí panel, protože řídicí panel a aplikace prohlížeče jsou vždy na různých doménách. Konfigurace CORS na řídicím panelu .NET.NET Aspire odebere omezení.

Pokud řídicí panel a vaši aplikaci spustí hostitel aplikace, nevyžaduje se žádná konfigurace CORS. .NET .NET Aspire řídicí panel automaticky nakonfiguruje tak, aby umožňoval všechny zdroje prostředků.

Pokud se řídicí panel používá jako standlone, musí být CORS nakonfigurovaný ručně. Doména použitá k zobrazení aplikace prohlížeče musí být nakonfigurována jako povolený původ zadáním proměnné prostředí DASHBOARD__OTLP__CORS__ALLOWEDORIGINS při spuštění kontejneru řídicího panelu:

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

Předchozí příkaz spustí kontejner řídicího panelu a nakonfiguruje https://localhost:8080 jako povolený zdroj. To znamená, že aplikace prohlížeče, ke které se přistupuje pomocí https://localhost:8080, má oprávnění odesílat telemetrii řídicího panelu.

Více původů může být povoleno s hodnotou oddělenou čárkami. Nebo všechny zdroje mohou být povoleny se zástupným znakem *. Například DASHBOARD__OTLP__CORS__ALLOWEDORIGINS=*.

Další informace naleznete v .NET.NET Aspire konfiguraci řídicího panelu: OTLP CORS.

Zabezpečení koncového bodu OTLP

Koncové body OTLP řídicího panelu lze zabezpečit autentizací pomocí klíče rozhraní API. Pokud je tato možnost povolená, musí požadavky HTTP OTLP na řídicím panelu obsahovat klíč rozhraní API jako hlavičku x-otlp-api-key. Ve výchozím nastavení se při každém spuštění řídicího panelu vygeneruje nový klíč rozhraní API.

Při spuštění řídicího panelu z hostitele aplikace se automaticky povolí ověřování pomocí klíče rozhraní API. Ověřování řídicího panelu lze zakázat nastavením DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS na true v souboru launchSettings hostitele aplikacejson.

Koncové body OTLP jsou ve výchozím nastavení na samostatném řídicím panelu nezabezpečené.

Konfigurace aplikace prohlížeče

Aplikace prohlížeče používá JavaScript OTEL SDK k odesílání telemetrie na řídicí panel. Úspěšné odesílání telemetrie na řídicí panel vyžaduje, aby sada SDK byla správně nakonfigurovaná.

Vývozce OTLP

Exportéry OTLP musí být součástí aplikace prohlížeče a nakonfigurované se sadou SDK. Export distribuovaného trasování pomocí OTLP například používá balíček @opentelemetry/exporter-trace-otlp-proto.

Při přidání OTLP do sady SDK je nutné zadat možnosti OTLP. Možnosti OTLP zahrnují:

  • url: Adresa, na kterou jsou provedeny požadavky HTTP OTLP. Adresa by měla být koncový bod HTTP OTLP řídicího panelu a cesta k rozhraní HTTP API OTLP. Například https://localhost:4318/v1/traces pro vývozce trasování OTLP. Pokud je aplikace prohlížeče spuštěna hostitelem aplikace, koncový bod HTTP OTLP je k dispozici z proměnné prostředí OTEL_EXPORTER_OTLP_ENDPOINT.

  • headers: Hlavičky odeslané s požadavky. Pokud je povolené ověřování klíče rozhraní API koncového bodu OTLP, musí být hlavička x-otlp-api-key odeslána s požadavky OTLP. Pokud je aplikace prohlížeče spuštěna hostitelem aplikace, klíč rozhraní API je k dispozici z proměnné prostředí OTEL_EXPORTER_OTLP_HEADERS.

Metadata prohlížeče

Pokud je aplikace prohlížeče nakonfigurovaná pro shromažďování distribuovaných tras, může nastavit trace parent pro jednotlivé úseky prohlížeče pomocí elementu meta v HTML. Hodnota metaelementu name="traceparent" by měla odpovídat aktuálnímu trasování.

V aplikaci .NET by se například hodnota nadřazeného trasování pravděpodobně přiřadila z Activity.Current a její hodnota Activity.Id by se předala jako content. Představte si například následující kód Razor:

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

Předchozí kód nastaví traceparent meta element na aktuální ID aktivity.

Příklad kódu telemetrie prohlížeče

Následující kód JavaScriptu ukazuje inicializaci sady OpenTelemetry JavaScript SDK a odesílání telemetrických dat na řídicí panel:

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;
}

Předchozí kód JavaScriptu definuje funkci initializeTelemetry, která očekává adresu URL koncového bodu OTLP, hlavičky a atributy prostředků. Tyto parametry poskytuje aplikace využívající prohlížeč, která je načítá z proměnných prostředí nastavených hostitelem aplikace. Představte si následující kód Razor:

@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>

Tip

Sdružování a minifikace kódu JavaScriptu je nad rámec tohoto článku.

Kompletní funkční příklad, jak nakonfigurovat sadu JavaScript OTEL SDK pro odesílání telemetrie na řídicí panel, najdete v ukázce prohlížečové telemetrie .

Viz také