From 6c7475ad65d9e1602b882c787db45f09348d831d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 14 Nov 2025 18:44:25 +0000
Subject: [PATCH 1/5] Initial plan
From 01ec8a3500411579ac3afd6f3b482127eb047772 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 14 Nov 2025 18:57:45 +0000
Subject: [PATCH 2/5] Add PivotSelector for browser telemetry with Razor Pages
JavaScript and Blazor WebAssembly options
Co-authored-by: IEvangelist <7679720+IEvangelist@users.noreply.github.com>
---
.../dashboard/enable-browser-telemetry.mdx | 94 ++++++++++++++++++-
1 file changed, 92 insertions(+), 2 deletions(-)
diff --git a/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx b/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx
index 799bedf..839997a 100644
--- a/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx
+++ b/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx
@@ -5,10 +5,21 @@ description: Learn how to enable browser telemetry in the Aspire dashboard.
import LearnMore from '@components/LearnMore.astro';
import { Aside, Tabs, TabItem } from '@astrojs/starlight/components';
+import PivotSelector from '@components/PivotSelector.astro';
+import Pivot from '@components/Pivot.astro';
-The Aspire dashboard can be configured to receive telemetry sent from browser apps. This feature is useful for monitoring client-side performance and user interactions. Browser telemetry requires additional dashboard configuration and that the [JavaScript OTEL SDK](https://opentelemetry.io/docs/languages/js/getting-started/browser/) is added to the browser apps.
+The Aspire dashboard can be configured to receive telemetry sent from browser apps. This feature is useful for monitoring client-side performance and user interactions. Browser telemetry requires additional dashboard configuration and that OpenTelemetry is configured in the browser app.
-This article discusses how to enable browser telemetry in the Aspire dashboard.
+This article discusses how to enable browser telemetry in the Aspire dashboard and provides examples for different approaches.
+
+
## Dashboard configuration
@@ -170,6 +181,8 @@ OTLP endpoints are unsecured by default in the standalone dashboard.
## Browser app configuration
+
+
A browser app uses the [JavaScript OTEL SDK](https://opentelemetry.io/docs/languages/js/getting-started/browser/) to send telemetry to the dashboard. Successfully sending telemetry to the dashboard requires the SDK to be correctly configured.
### OTLP exporter
@@ -305,6 +318,83 @@ The bundling and minification of the JavaScript code is beyond the scope of this
For the complete working example of how to configure the JavaScript OTEL SDK to send telemetry to the dashboard, see the [browser telemetry sample](https://github.com/dotnet/aspire/tree/main/playground/BrowserTelemetry).
+
+
+
+
+Blazor WebAssembly apps can send telemetry to the dashboard using the .NET OpenTelemetry packages. This approach allows you to use familiar .NET APIs instead of JavaScript for telemetry configuration.
+
+### Add OpenTelemetry packages
+
+Add the following NuGet packages to your Blazor WebAssembly project:
+
+```xml
+
+
+
+
+
+```
+
+### Configure OpenTelemetry in a component
+
+Create a component or add the following code to an existing component to configure OpenTelemetry:
+
+```razor
+@using OpenTelemetry
+@using OpenTelemetry.Resources
+@using OpenTelemetry.Trace
+@using System.Diagnostics
+
+
+
+@code {
+ private void Trace()
+ {
+ var resourceBuilder = ResourceBuilder.CreateDefault()
+ .AddService("blazor-otel");
+
+ using var otel = Sdk.CreateTracerProviderBuilder()
+ .SetResourceBuilder(resourceBuilder)
+ .AddSource("ui")
+ .AddOtlpExporter(options =>
+ {
+ options.Endpoint = new Uri("https://localhost:21036");
+ options.ExportProcessorType = ExportProcessorType.Simple;
+ })
+ .Build();
+
+ using var source = new ActivitySource("ui");
+ using (var activity = source.StartActivity("trace-click", ActivityKind.Client))
+ {
+ activity?.AddEvent(new ActivityEvent("Trace button click"));
+ }
+ }
+}
+```
+
+The preceding code:
+
+- Creates a resource builder with a service name of `blazor-otel`.
+- Configures the tracer provider to use an OTLP exporter that sends data to the dashboard.
+- Creates an activity source and starts a new activity when the button is clicked.
+- Adds an event to the activity.
+
+
+
+### Best practices
+
+For production applications, consider the following best practices:
+
+- Initialize the tracer provider once during application startup rather than on each trace operation.
+- Use dependency injection to provide the tracer provider to components.
+- Configure the OTLP endpoint and other settings from configuration or environment variables.
+- Handle authentication headers if OTLP endpoint API key authentication is enabled.
+
+
+
## See also
- [Aspire dashboard configuration](/dashboard/configuration/)
From a002d0a82ccb39338cb446b2cc7e8b6334c7e0e1 Mon Sep 17 00:00:00 2001
From: David Pine
Date: Tue, 18 Nov 2025 18:53:51 +0000
Subject: [PATCH 3/5] cleanup: Enhance browser telemetry documentation with
Blazor WebAssembly examples and configuration details
---
.../dashboard/enable-browser-telemetry.mdx | 186 ++++++++++++------
1 file changed, 130 insertions(+), 56 deletions(-)
diff --git a/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx b/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx
index 839997a..61bb1f6 100644
--- a/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx
+++ b/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx
@@ -185,23 +185,104 @@ OTLP endpoints are unsecured by default in the standalone dashboard.
A browser app uses the [JavaScript OTEL SDK](https://opentelemetry.io/docs/languages/js/getting-started/browser/) to send telemetry to the dashboard. Successfully sending telemetry to the dashboard requires the SDK to be correctly configured.
-### OTLP exporter
+
+
+
+Blazor WebAssembly apps can send telemetry to the dashboard using the .NET OpenTelemetry packages. This approach allows you to use familiar .NET APIs instead of JavaScript for telemetry configuration.
+
+
+
+### Install required packages
+
+
OTLP exporters must be included in the browser app and configured with the SDK. For example, exporting distributed tracing with OTLP uses the [@opentelemetry/exporter-trace-otlp-proto](https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-proto) package.
+
+
+
+Add the following NuGet packages to your Blazor WebAssembly project:
+
+```xml title="XML — C# project file"
+
+
+
+
+
+```
+
+
+
+### Configure OpenTelemetry
+
+
+
When OTLP is added to the SDK, OTLP options must be specified. OTLP options includes:
- `url`: The address that HTTP OTLP requests are made to. The address should be the dashboard HTTP OTLP endpoint and the path to the OTLP HTTP API. For example, `https://localhost:4318/v1/traces` for the trace OTLP exporter. If the browser app is launched by the AppHost then the HTTP OTLP endpoint is available from the `OTEL_EXPORTER_OTLP_ENDPOINT` environment variable.
- `headers`: The headers sent with requests. If OTLP endpoint API key authentication is enabled the `x-otlp-api-key` header must be sent with OTLP requests. If the browser app is launched by the AppHost then the API key is available from the `OTEL_EXPORTER_OTLP_HEADERS` environment variable.
-### Browser metadata
+
+
+
+Create a component or add the following code to an existing component to configure OpenTelemetry:
+
+```razor title="Razor — Components/Trace.razor"
+@using OpenTelemetry
+@using OpenTelemetry.Resources
+@using OpenTelemetry.Trace
+@using System.Diagnostics
+
+
+
+@code {
+ private void Trace()
+ {
+ var resourceBuilder = ResourceBuilder.CreateDefault()
+ .AddService("blazor-otel");
+
+ using var otel = Sdk.CreateTracerProviderBuilder()
+ .SetResourceBuilder(resourceBuilder)
+ .AddSource("ui")
+ .AddOtlpExporter(options =>
+ {
+ options.Endpoint = new Uri("https://localhost:21036");
+ options.ExportProcessorType = ExportProcessorType.Simple;
+ })
+ .Build();
+
+ using var source = new ActivitySource("ui");
+ using (var activity = source.StartActivity("trace-click", ActivityKind.Client))
+ {
+ activity?.AddEvent(new ActivityEvent("Trace button click"));
+ }
+ }
+}
+```
+
+The preceding code:
+
+- Creates a resource builder with a service name of `blazor-otel`.
+- Configures the tracer provider to use an OTLP exporter that sends data to the dashboard.
+- Creates an activity source and starts a new activity when the button is clicked.
+- Adds an event to the activity.
+
+
+
+
+
+### Set trace context
+
+
When a browser app is configured to collect distributed traces, the browser app can set the trace parent a browser's spans using the `meta` element in the HTML. The value of the `name="traceparent"` meta element should correspond to the current trace.
In a .NET app, for example, the trace parent value would likely be assigned from the `Activity.Current` and passing its `Activity.Id` value as the `content`. For example, consider the following Razor code:
-```razor
+```razor title="Razor — Layout.razor"
@if (Activity.Current is { } currentActivity)
{
@@ -213,11 +294,25 @@ In a .NET app, for example, the trace parent value would likely be assigned from
The preceding code sets the `traceparent` meta element to the current activity ID.
-## Example browser telemetry code
+
+
+
+For production applications, consider the following best practices:
+
+- Initialize the tracer provider once during application startup rather than on each trace operation.
+- Use dependency injection to provide the tracer provider to components.
+- Configure the OTLP endpoint and other settings from configuration or environment variables.
+- Handle authentication headers if OTLP endpoint API key authentication is enabled.
+
+
+
+## Example implementation
+
+
The following JavaScript code demonstrates the initialization of the OpenTelemetry JavaScript SDK and the sending of telemetry data to the dashboard:
-```javascript
+```javascript title="JavaScript — index.js"
import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
@@ -268,7 +363,7 @@ function parseDelimitedValues(s) {
The preceding JavaScript code defines an `initializeTelemetry` function that expects the OTLP endpoint URL, the headers, and the resource attributes. These parameters are provided by the consuming browser app that pulls them from the environment variables set by the app host. Consider the following Razor code:
-```razor {32-39}
+```razor title="Razor — Layout.razor" {32-39}
@using System.Diagnostics
@@ -319,79 +414,58 @@ The bundling and minification of the JavaScript code is beyond the scope of this
For the complete working example of how to configure the JavaScript OTEL SDK to send telemetry to the dashboard, see the [browser telemetry sample](https://github.com/dotnet/aspire/tree/main/playground/BrowserTelemetry).
-
-Blazor WebAssembly apps can send telemetry to the dashboard using the .NET OpenTelemetry packages. This approach allows you to use familiar .NET APIs instead of JavaScript for telemetry configuration.
-
-### Add OpenTelemetry packages
-
-Add the following NuGet packages to your Blazor WebAssembly project:
-
-```xml
-
-
-
-
-
-```
-
-### Configure OpenTelemetry in a component
-
-Create a component or add the following code to an existing component to configure OpenTelemetry:
+The following example demonstrates a complete implementation using Blazor WebAssembly. For a full working sample, refer to the Aspire samples repository.
-```razor
+```razor title="Razor — Pages/Telemetry.razor"
+@page "/telemetry"
@using OpenTelemetry
@using OpenTelemetry.Resources
@using OpenTelemetry.Trace
@using System.Diagnostics
-
+
Browser Telemetry Example
+
@code {
- private void Trace()
+ private TracerProvider? _tracerProvider;
+ private ActivitySource? _activitySource;
+
+ protected override void OnInitialized()
{
var resourceBuilder = ResourceBuilder.CreateDefault()
- .AddService("blazor-otel");
+ .AddService("blazor-browser-telemetry");
- using var otel = Sdk.CreateTracerProviderBuilder()
+ _tracerProvider = Sdk.CreateTracerProviderBuilder()
.SetResourceBuilder(resourceBuilder)
- .AddSource("ui")
+ .AddSource("browser-app")
.AddOtlpExporter(options =>
{
- options.Endpoint = new Uri("https://localhost:21036");
+ var endpoint = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT")
+ ?? "https://localhost:21036";
+ options.Endpoint = new Uri(endpoint);
options.ExportProcessorType = ExportProcessorType.Simple;
})
.Build();
- using var source = new ActivitySource("ui");
- using (var activity = source.StartActivity("trace-click", ActivityKind.Client))
- {
- activity?.AddEvent(new ActivityEvent("Trace button click"));
- }
+ _activitySource = new ActivitySource("browser-app");
}
-}
-```
-
-The preceding code:
-
-- Creates a resource builder with a service name of `blazor-otel`.
-- Configures the tracer provider to use an OTLP exporter that sends data to the dashboard.
-- Creates an activity source and starts a new activity when the button is clicked.
-- Adds an event to the activity.
-
-
-### Best practices
-
-For production applications, consider the following best practices:
+ private void SendTrace()
+ {
+ using var activity = _activitySource?.StartActivity("user-action", ActivityKind.Client);
+ activity?.AddEvent(new ActivityEvent("Button clicked"));
+ activity?.SetTag("user.action", "send-trace");
+ }
-- Initialize the tracer provider once during application startup rather than on each trace operation.
-- Use dependency injection to provide the tracer provider to components.
-- Configure the OTLP endpoint and other settings from configuration or environment variables.
-- Handle authentication headers if OTLP endpoint API key authentication is enabled.
+ public void Dispose()
+ {
+ _activitySource?.Dispose();
+ _tracerProvider?.Dispose();
+ }
+}
+```
From 481c3b5e3de25d5e768fc42d26099774e130b286 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 18 Nov 2025 19:02:47 +0000
Subject: [PATCH 4/5] Fix Blazor OTEL example to follow best practices and use
correct port
Co-authored-by: IEvangelist <7679720+IEvangelist@users.noreply.github.com>
---
.../dashboard/enable-browser-telemetry.mdx | 40 +++++++++++++------
1 file changed, 28 insertions(+), 12 deletions(-)
diff --git a/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx b/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx
index 61bb1f6..dddb311 100644
--- a/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx
+++ b/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx
@@ -233,43 +233,59 @@ Create a component or add the following code to an existing component to configu
@using OpenTelemetry.Resources
@using OpenTelemetry.Trace
@using System.Diagnostics
+@implements IDisposable
@code {
- private void Trace()
+ private TracerProvider? _tracerProvider;
+ private ActivitySource? _activitySource;
+
+ protected override void OnInitialized()
{
var resourceBuilder = ResourceBuilder.CreateDefault()
.AddService("blazor-otel");
- using var otel = Sdk.CreateTracerProviderBuilder()
+ _tracerProvider = Sdk.CreateTracerProviderBuilder()
.SetResourceBuilder(resourceBuilder)
.AddSource("ui")
.AddOtlpExporter(options =>
{
- options.Endpoint = new Uri("https://localhost:21036");
+ var endpoint = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT")
+ ?? "https://localhost:4318";
+ options.Endpoint = new Uri(endpoint);
options.ExportProcessorType = ExportProcessorType.Simple;
})
.Build();
- using var source = new ActivitySource("ui");
- using (var activity = source.StartActivity("trace-click", ActivityKind.Client))
- {
- activity?.AddEvent(new ActivityEvent("Trace button click"));
- }
+ _activitySource = new ActivitySource("ui");
+ }
+
+ private void Trace()
+ {
+ using var activity = _activitySource?.StartActivity("trace-click", ActivityKind.Client);
+ activity?.AddEvent(new ActivityEvent("Trace button click"));
+ }
+
+ public void Dispose()
+ {
+ _activitySource?.Dispose();
+ _tracerProvider?.Dispose();
}
}
```
The preceding code:
+- Initializes the `TracerProvider` and `ActivitySource` once during component initialization in `OnInitialized()`.
- Creates a resource builder with a service name of `blazor-otel`.
- Configures the tracer provider to use an OTLP exporter that sends data to the dashboard.
-- Creates an activity source and starts a new activity when the button is clicked.
-- Adds an event to the activity.
+- Uses the `OTEL_EXPORTER_OTLP_ENDPOINT` environment variable if available, otherwise defaults to `https://localhost:4318`.
+- Creates an activity when the button is clicked and adds an event to it.
+- Properly disposes of the tracer provider and activity source when the component is disposed.
@@ -443,7 +459,7 @@ The following example demonstrates a complete implementation using Blazor WebAss
.AddOtlpExporter(options =>
{
var endpoint = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT")
- ?? "https://localhost:21036";
+ ?? "https://localhost:4318";
options.Endpoint = new Uri(endpoint);
options.ExportProcessorType = ExportProcessorType.Simple;
})
From 61cf7a0f4ca4ca848dedc58df8ccd606c4e84886 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 19 Nov 2025 03:41:15 +0000
Subject: [PATCH 5/5] Fix Blazor OTEL examples: add HttpProtobuf protocol and
header support
Co-authored-by: IEvangelist <7679720+IEvangelist@users.noreply.github.com>
---
.../dashboard/enable-browser-telemetry.mdx | 42 +++++++++++++++++--
1 file changed, 38 insertions(+), 4 deletions(-)
diff --git a/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx b/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx
index dddb311..5b1b4cb 100644
--- a/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx
+++ b/src/frontend/src/content/docs/dashboard/enable-browser-telemetry.mdx
@@ -230,6 +230,7 @@ Create a component or add the following code to an existing component to configu
```razor title="Razor — Components/Trace.razor"
@using OpenTelemetry
+@using OpenTelemetry.Exporter
@using OpenTelemetry.Resources
@using OpenTelemetry.Trace
@using System.Diagnostics
@@ -254,7 +255,22 @@ Create a component or add the following code to an existing component to configu
var endpoint = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT")
?? "https://localhost:4318";
options.Endpoint = new Uri(endpoint);
+ options.Protocol = OtlpExportProtocol.HttpProtobuf;
options.ExportProcessorType = ExportProcessorType.Simple;
+
+ // Add API key header if available
+ var headers = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_HEADERS");
+ if (!string.IsNullOrEmpty(headers))
+ {
+ foreach (var header in headers.Split(','))
+ {
+ var parts = header.Split('=', 2);
+ if (parts.Length == 2)
+ {
+ options.Headers = $"{parts[0].Trim()}={parts[1].Trim()}";
+ }
+ }
+ }
})
.Build();
@@ -279,13 +295,14 @@ The preceding code:
- Initializes the `TracerProvider` and `ActivitySource` once during component initialization in `OnInitialized()`.
- Creates a resource builder with a service name of `blazor-otel`.
-- Configures the tracer provider to use an OTLP exporter that sends data to the dashboard.
-- Uses the `OTEL_EXPORTER_OTLP_ENDPOINT` environment variable if available, otherwise defaults to `https://localhost:4318`.
+- Configures the tracer provider to use an OTLP exporter with `HttpProtobuf` protocol (required for browser compatibility).
+- Reads the endpoint from `OTEL_EXPORTER_OTLP_ENDPOINT` environment variable if available, otherwise defaults to `https://localhost:4318`.
+- Parses and applies authentication headers from `OTEL_EXPORTER_OTLP_HEADERS` if present (e.g., for API key authentication).
- Creates an activity when the button is clicked and adds an event to it.
- Properly disposes of the tracer provider and activity source when the component is disposed.
-