ブラウザー テレメトリを有効にする
.NET .NET Aspire ダッシュボードは、ブラウザー アプリから送信されたテレメトリを受信するように構成できます。 この機能は、client側のパフォーマンスとユーザーの操作を監視するのに役立ちます。 ブラウザー テレメトリには、追加のダッシュボード構成が必要であり、JavaScript OTEL SDK がブラウザー アプリに追加されます。
この記事では、.NET.NET Aspire ダッシュボードでブラウザー テレメトリを有効にする方法について説明します。
ダッシュボードの構成
ブラウザー テレメトリでは、次の機能を有効にするためにダッシュボードが必要です。
- OTLP HTTP エンドポイント。 このエンドポイントは、ブラウザー アプリからテレメトリを受信するためにダッシュボードによって使用されます。
- クロスオリジン リソース共有 (CORS)。 CORS を使用すると、ブラウザー アプリはダッシュボードに要求を行うことができます。
OTLP 構成
.NET .NET Aspire ダッシュボードは、OTLP エンドポイントを介してテレメトリを受信します。 HTTP OTLP エンドポイント と gRPC OTLP エンドポイントは、ダッシュボードでサポートされています。 ブラウザー アプリでは gRPC がサポートされていないため、ブラウザー アプリは HTTP OLTP を使用してテレメトリをダッシュボードに送信する必要があります。
gPRC または HTTP エンドポイントを構成するには、次の環境変数を指定します。
-
DOTNET_DASHBOARD_OTLP_ENDPOINT_URL
: ダッシュボードがデータに接続する gRPC エンドポイント。 -
DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL
: ダッシュボードがデータに接続する HTTP エンドポイント。
HTTP OTLP エンドポイントの構成は、ダッシュボードがアプリ ホストによって開始されているか、スタンドアロンで実行されているかによって異なります。
アプリ ホストで OTLP HTTP を構成する
ダッシュボードとアプリがアプリ ホストによって起動されている場合、ダッシュボードのOTLPエンドポイントは、アプリ ホストののlaunchSettingsファイル内で構成されます (json)。
次の 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"
}
}
}
}
上記の起動設定 JSON ファイルは、DOTNET_DASHBOARD_OTLP_HTTP_ENDPOINT_URL
環境変数を含むようにすべてのプロファイルを構成します。
スタンドアロン ダッシュボードを使用して OTLP HTTP を構成する
ダッシュボードがスタンドアロンで使用され、.NET Aspireの rest がない場合、ポート 18890
で OTLP HTTP エンドポイントが既定で有効になります。 ただし、ダッシュボード コンテナーの起動時にポートをマップする必要があります。
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
上記のコマンドは、ダッシュボード コンテナーを実行し、gRPC OTLP をポート 4317
にマップし、HTTP OTLP をポート 4318
にマップします。
CORS 構成
既定では、ブラウザー アプリはクロス ドメイン API 呼び出しを行うことを制限されます。 これは、ダッシュボードとブラウザー アプリが常に異なるドメイン上にあるため、ダッシュボードへのテレメトリの送信に影響します。 .NET .NET Aspire ダッシュボードで CORS を構成すると、制限が解除されます。
ダッシュボードとアプリがアプリ ホストによって起動されている場合、CORS 構成は必要ありません。 .NET .NET Aspire は、すべてのリソースの配信元を許可するようにダッシュボードを自動的に構成します。
ダッシュボードを単独で使用する場合は、CORS を手動で構成する必要があります。 ブラウザー アプリの表示に使用するドメインは、ダッシュボード コンテナーの起動時に DASHBOARD__OTLP__CORS__ALLOWEDORIGINS
環境変数を指定して、許可された配信元として構成する必要があります。
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
上記のコマンドは、ダッシュボード コンテナーを実行し、許可された配信元として https://localhost:8080
を構成します。 つまり、https://localhost:8080
を使用してアクセスされるブラウザー アプリには、ダッシュボード テレメトリを送信するアクセス許可があります。
コンマ区切りの値を使用して、複数のオリジンを使用できます。 または、*
ワイルドカードを使用して、すべてのオリジンを許可することもできます。 たとえば、DASHBOARD__OTLP__CORS__ALLOWEDORIGINS=*
します。
詳細については、「.NET.NET Aspire ダッシュボードの構成: OTLP CORS」を参照してください。
OTLP エンドポイントのセキュリティ
ダッシュボード OTLP エンドポイントは、API キー認証を使用してセキュリティで保護できます。 有効になっている場合、ダッシュボードへの HTTP OTLP 要求には、x-otlp-api-key
ヘッダーとして API キーを含める必要があります。 既定では、ダッシュボードが実行されるたびに新しい API キーが生成されます。
アプリ ホストからダッシュボードを実行すると、API キー認証が自動的に有効になります。 ダッシュボード認証は、アプリホストの launchSettings ファイル内の DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS
を true
に設定することで無効にできます。ファイルjson。
OTLP エンドポイントは、スタンドアロン ダッシュボードでは既定ではセキュリティで保護されません。
ブラウザー アプリの構成
ブラウザー アプリは、JavaScript OTEL SDK を使用して、テレメトリをダッシュボードに送信します。 ダッシュボードにテレメトリを正常に送信するには、SDK を正しく構成する必要があります。
OTLP エクスポーター
OTLP エクスポーターは、ブラウザー アプリに含め、SDK で構成する必要があります。 たとえば、OTLP を使用して分散トレースをエクスポートする場合、@opentelemetry/exporter-trace-otlp-proto パッケージが使用されます。
OTLP を SDK に追加する場合は、OTLP オプションを指定する必要があります。 OTLP オプションには、次のものが含まれます。
url
: HTTP OTLP 要求が行われるアドレス。 アドレスは、ダッシュボードの HTTP OTLP エンドポイントと OTLP HTTP API へのパスである必要があります。 たとえば、トレース OTLP エクスポーターのhttps://localhost:4318/v1/traces
。 ブラウザー アプリがアプリ ホストによって起動された場合は、OTEL_EXPORTER_OTLP_ENDPOINT
環境変数から HTTP OTLP エンドポイントを使用できます。headers
: 要求と共に送信されたヘッダー。 OTLP エンドポイント API キー認証が有効になっている場合は、x-otlp-api-key
ヘッダーを OTLP 要求と共に送信する必要があります。 ブラウザー アプリがアプリ ホストによって起動された場合は、OTEL_EXPORTER_OTLP_HEADERS
環境変数から API キーを使用できます。
ブラウザーのメタデータ
ブラウザー アプリが分散トレースを収集するように構成されている場合、ブラウザー アプリは、HTML 内の meta
要素を使用して、ブラウザーのスパンをトレース親に設定できます。
name="traceparent"
メタ要素の値は、現在のトレースに対応している必要があります。
たとえば、.NET アプリでは、トレースの親値が Activity.Current から割り当てられ、その Activity.Id 値が content
として渡される可能性があります。 たとえば、次の Razor コードを考えてみましょう。
<head>
@if (Activity.Current is { } currentActivity)
{
<meta name="traceparent" content="@currentActivity.Id" />
}
<!-- Other elements omitted for brevity... -->
</head>
上記のコードは、traceparent
メタ要素を現在のアクティビティ ID に設定します。
ブラウザー テレメトリ コードの例
次の JavaScript コードは、OpenTelemetry JavaScript SDK の初期化と、ダッシュボードへのテレメトリ データの送信を示しています。
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;
}
上記の JavaScript コードでは、OTLP エンドポイント URL、ヘッダー、およびリソース属性を想定する initializeTelemetry
関数が定義されています。 これらのパラメーターは、アプリ ホストによって設定された環境変数からそれらをプルする、使用しているブラウザー アプリによって提供されます。 次の 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>
ヒント
JavaScript コードのバンドルと縮小は、この記事の範囲外です。
テレメトリをダッシュボードに送信するように JavaScript OTEL SDK を構成する方法の完全な作業例については、ブラウザーテレメトリサンプルを参照してください。
関連項目
.NET Aspire