Udostępnij za pośrednictwem


Włączanie telemetrii przeglądarki

Pulpit nawigacyjny .NET.NET Aspire można skonfigurować do odbierania danych telemetrycznych wysyłanych z aplikacji przeglądarki. Ta funkcja jest przydatna do monitorowania wydajności po stronie clienti interakcji użytkowników. Dane telemetryczne przeglądarki wymagają dodatkowej konfiguracji panelu kontrolnego oraz dodania SDK OTEL JavaScript do aplikacji przeglądarki.

W tym artykule omówiono sposób włączania telemetrii przeglądarki na pulpicie nawigacyjnym .NET.NET Aspire.

Konfiguracja pulpitu nawigacyjnego

Telemetria przeglądarki wymaga, aby pulpit nawigacyjny włączył następujące funkcje:

  • Punkt końcowy HTTP OTLP. Ten punkt końcowy jest używany przez pulpit nawigacyjny do odbierania danych telemetrycznych z aplikacji przeglądarki.
  • Współużytkowanie zasobów między źródłami (CORS). Mechanizm CORS umożliwia aplikacjom przeglądarki wykonywanie żądań do pulpitu nawigacyjnego.

Konfiguracja OTLP

Pulpit nawigacyjny .NET.NET Aspire odbiera dane telemetryczne za pośrednictwem punktów końcowych OTLP. punkty końcowe HTTP OTLP i punkty końcowe OTLP gRPC są obsługiwane przez pulpit nawigacyjny. Aplikacje przeglądarki muszą używać protokołu HTTP OLTP do wysyłania danych telemetrycznych do pulpitu nawigacyjnego, ponieważ aplikacje przeglądarki nie obsługują funkcji gRPC.

Aby skonfigurować punkty końcowe gPRC lub HTTP, określ następujące zmienne środowiskowe:

  • DOTNET_DASHBOARD_OTLP_ENDPOINT_URL: Punkt końcowy gRPC, do którego pulpit nawigacyjny łączy się swoimi danymi.
  • DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL: punkt końcowy HTTP, z którym pulpit nawigacyjny łączy się ze swoimi danymi.

Konfiguracja punktu końcowego HTTP OTLP zależy od tego, czy pulpit nawigacyjny jest uruchamiany przez hosta aplikacji, czy jest uruchamiany autonomicznie.

Konfigurowanie protokołu HTTP OTLP przy użyciu hosta aplikacji

Jeśli pulpit nawigacyjny i aplikacja są uruchamiane przez hosta aplikacji, punkty końcowe OTLP pulpitu nawigacyjnego są konfigurowane w launchSettings hosta aplikacji.json pliku.

Rozważmy następujący przykładowy plik 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"
      }
    }
  }
}

Plik z poprzednimi ustawieniami uruchamiania JSON konfiguruje wszystkie profile do uwzględnienia zmiennej środowiskowej DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL.

Konfigurowanie protokołu HTTP OTLP z samodzielnym pulpitem nawigacyjnym

Jeśli pulpit nawigacyjny jest używany autonomicznie, bez rest i .NET Aspire, punkt końcowy HTTP OTLP jest domyślnie włączony na porcie 18890. Jednak port musi zostać zamapowany po uruchomieniu kontenera pulpitu nawigacyjnego:

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

Poprzednie polecenie uruchamia kontener dashboardu i przypisuje gRPC OTLP do portu 4317 oraz HTTP OTLP do portu 4318.

Konfiguracja mechanizmu CORS

Domyślnie aplikacje przeglądarki są ograniczone do wykonywania wywołań interfejsu API między domenami. Ma to wpływ na wysyłanie danych telemetrycznych do pulpitu nawigacyjnego, ponieważ pulpit nawigacyjny i aplikacja przeglądarki są zawsze w różnych domenach. Skonfigurowanie mechanizmu CORS na pulpicie nawigacyjnym .NET.NET Aspire spowoduje usunięcie ograniczenia.

Jeśli pulpit nawigacyjny i aplikacja są uruchamiane przez hosta aplikacji, nie jest wymagana żadna konfiguracja mechanizmu CORS. .NET .NET Aspire automatycznie konfiguruje pulpit nawigacyjny tak, aby zezwalał na wszystkie źródła zasobów.

Jeśli pulpit nawigacyjny jest używany autonomicznie, mechanizm CORS należy skonfigurować ręcznie. Domena używana do wyświetlania aplikacji przeglądarki musi być skonfigurowana jako dozwolone źródło, określając zmienną środowiskową DASHBOARD__OTLP__CORS__ALLOWEDORIGINS po uruchomieniu kontenera pulpitu nawigacyjnego:

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

Poprzednie polecenie uruchamia kontener pulpitu nawigacyjnego i konfiguruje https://localhost:8080 jako dozwolone źródło. Oznacza to, że aplikacja przeglądarki, która jest uzyskiwana przy użyciu https://localhost:8080 ma uprawnienia do wysyłania danych telemetrycznych pulpitu nawigacyjnego.

Wiele źródeł może być dozwolonych z wartością rozdzielaną przecinkami. Można również zezwolić na wszystkie źródła za pomocą symbolu wieloznacznego *. Na przykład DASHBOARD__OTLP__CORS__ALLOWEDORIGINS=*.

Aby uzyskać więcej informacji, zobacz konfigurację pulpitu nawigacyjnego .NET.NET Aspire: OTLP CORS.

Zabezpieczenia punktu końcowego OTLP

Punkty końcowe OTLP pulpitu nawigacyjnego można zabezpieczyć za pomocą uwierzytelniania klucza API. Gdy jest włączone, żądania HTTP OTLP do pulpitu nawigacyjnego muszą zawierać klucz interfejsu API jako nagłówek x-otlp-api-key. Domyślnie nowy klucz interfejsu API jest generowany przy każdym uruchomieniu pulpitu nawigacyjnego.

Uwierzytelnianie klucza interfejsu API jest automatycznie włączane po uruchomieniu pulpitu nawigacyjnego z hosta aplikacji. Uwierzytelnianie pulpitu nawigacyjnego można wyłączyć, ustawiając DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS na true w launchSettings hosta aplikacji.json plik.

Punkty końcowe OTLP są domyślnie niezabezpieczone na autonomicznym pulpicie nawigacyjnym.

Konfiguracja aplikacji przeglądarki

Aplikacja przeglądarki używa zestawu SDK JavaScript OTEL do wysyłania danych telemetrycznych do pulpitu nawigacyjnego. Pomyślne wysłanie danych telemetrycznych do pulpitu nawigacyjnego wymaga poprawnego skonfigurowania zestawu SDK.

Eksporter OTLP

Eksporterzy OTLP muszą być dołączani do aplikacji przeglądarkowej i konfigurowani przy użyciu zestawu SDK. Na przykład, eksportowanie śledzenia rozproszonego przy użyciu OTLP wymaga pakietu @opentelemetry/exporter-trace-otlp-proto.

Po dodaniu funkcji OTLP do zestawu SDK należy określić opcje OTLP. Opcje OTLP obejmują:

  • url: adres, do którego są wysyłane żądania HTTP OTLP. Adres powinien być punktem końcowym konsoli HTTP OTLP oraz zawierać ścieżkę do interfejsu API HTTP OTLP. Na przykład https://localhost:4318/v1/traces dla eksportera śledzenia OTLP. Jeśli aplikacja przeglądarki jest uruchamiana przez hosta aplikacji, punkt końcowy HTTP OTLP jest dostępny ze zmiennej środowiskowej OTEL_EXPORTER_OTLP_ENDPOINT.

  • headers: Nagłówki wysyłane wraz z żądaniami. Jeśli uwierzytelnianie za pomocą klucza API dla punktu końcowego OTLP jest włączone, nagłówek x-otlp-api-key musi być wysyłany z żądaniami OTLP. Jeśli aplikacja przeglądarki jest uruchamiana przez hosta aplikacji, klucz interfejsu API jest dostępny ze zmiennej środowiskowej OTEL_EXPORTER_OTLP_HEADERS.

Metadane przeglądarki

Gdy aplikacja przeglądarki jest skonfigurowana do zbierania rozproszonych śladów, może ustawić nadrzędny ślad dla zakresów przeglądarki przy użyciu elementu meta w kodzie HTML. Wartość elementu meta name="traceparent" powinna odpowiadać bieżącemu prześledzeniu.

Na przykład, w aplikacji .NET wartość nadrzędna śledzenia prawdopodobnie zostanie przypisana z Activity.Current, a jej wartość Activity.Id zostanie przekazana jako content. Rozważmy na przykład następujący kod Razor:

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

Powyższy kod ustawia element meta traceparent na bieżący identyfikator działania.

Przykładowy kod telemetrii przeglądarki

Poniższy kod JavaScript demonstruje inicjowanie zestawu SDK języka JavaScript OpenTelemetry i wysyłanie danych telemetrycznych do pulpitu nawigacyjnego:

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

Powyższy kod JavaScript definiuje funkcję initializeTelemetry, która oczekuje adresu URL punktu końcowego OTLP, nagłówków i atrybutów zasobu. Te parametry są dostarczane przez zużywającą aplikację przeglądarki, która pobiera je ze zmiennych środowiskowych ustawionych przez hosta aplikacji. Rozważmy następujący kod 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>

Wskazówka

Tworzenie pakietów i minimalizowanie kodu JavaScript wykracza poza zakres tego artykułu.

Aby zapoznać się z kompletnym działającym przykładem konfigurowania JavaScript OTEL SDK w celu wysyłania danych telemetrycznych do pulpitu nawigacyjnego, zobacz przykład telemetrii przeglądarki .

Zobacz też