브라우저 텔레메트리 사용
브라우저 앱에서 전송된 원격 분석을 수신하도록 .NET.NET Aspire 대시보드를 구성할 수 있습니다. 이 기능은 client-side 성능 및 사용자 상호 작용을 모니터링하는 데 유용합니다. 브라우저 원격 분석에는 추가적인 대시보드 구성이 필요하며, 브라우저 앱에 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와 HTTP OTLP를 각각 포트 4317
및 포트 4318
에 매핑합니다.
CORS 구성
기본적으로 브라우저 앱은 도메인 간 API 호출을 할 수 없습니다. 대시보드와 브라우저 앱은 항상 서로 다른 도메인에 있기 때문에 이는 대시보드에 원격 분석을 보내는 데 영향을 줍니다. .NET .NET Aspire 대시보드에서 CORS를 구성하면 제한이 제거됩니다.
대시보드와 앱이 앱 호스트에서 시작되는 경우 CORS 구성이 필요하지 않습니다. .NET .NET Aspire 모든 리소스 원본을 허용하도록 대시보드를 자동으로 구성합니다.
대시보드가 standlone을 사용하는 경우 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 요청에 API 키가 x-otlp-api-key
헤더로 포함되어야 합니다. 기본적으로 대시보드가 실행될 때마다 새 API 키가 생성됩니다.
API 키 인증은 앱 호스트에서 대시보드를 실행할 때 자동으로 사용하도록 설정됩니다. 앱 호스트의 launchSettings의json 파일에서 DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS
을 true
으로 설정하여 대시보드 인증을 비활성화할 수 있습니다.
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 경로여야 합니다. 예를 들어,https://localhost:4318/v1/traces
는 추적 OTLP 내보내기를 위한 것입니다. 앱 호스트에서 브라우저 앱을 시작하면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