BlazorAmpowering.Observability.WebAssembly
1.0.0
dotnet add package BlazorAmpowering.Observability.WebAssembly --version 1.0.0
NuGet\Install-Package BlazorAmpowering.Observability.WebAssembly -Version 1.0.0
<PackageReference Include="BlazorAmpowering.Observability.WebAssembly" Version="1.0.0" />
<PackageVersion Include="BlazorAmpowering.Observability.WebAssembly" Version="1.0.0" />
<PackageReference Include="BlazorAmpowering.Observability.WebAssembly" />
paket add BlazorAmpowering.Observability.WebAssembly --version 1.0.0
#r "nuget: BlazorAmpowering.Observability.WebAssembly, 1.0.0"
#:package BlazorAmpowering.Observability.WebAssembly@1.0.0
#addin nuget:?package=BlazorAmpowering.Observability.WebAssembly&version=1.0.0
#tool nuget:?package=BlazorAmpowering.Observability.WebAssembly&version=1.0.0
BlazorAmpowering.Observability.WebAssembly
Codeless OpenTelemetry instrumentation for Blazor WebAssembly applications.
Automatically propagates component context (component name, method, user event, client latency) to your Web API so every server-side trace is enriched with the WASM client context — no manual span creation required.
How it works
The WASM client automatically injects context headers into every outgoing HttpClient request. The Web API server — instrumented with BlazorAmpowering.Observability — receives these headers and attaches them to its own OpenTelemetry spans. All trace export and configuration lives on the server.
WASM Client Web API Server
────────────────────────────────── ──────────────────────────────────────────
WasmTraceContextHandler BlazorAmpowering.Observability
→ X-Blazor-Component: ProductList → reads headers
→ X-Blazor-Method: AddProductAsync → enriches OTel spans
→ X-Client-Latency-Ms: 42 → exports to Grafana / Tempo
Installation
WASM client project:
dotnet add package BlazorAmpowering.Observability.WebAssembly
Web API / host server project:
dotnet add package BlazorAmpowering.Observability
The OTel pipeline (traces, metrics, export) is configured entirely on the server.
See the BlazorAmpowering.Observability README for server configuration (appsettings.json, Program.cs).
Configuration
1. Server — appsettings.json
{
"OpenTelemetry": {
"Enabled": true,
"ApplicationName": "my-app",
"OtlpEndpoint": "http://localhost:4318/v1/traces",
"OtlpMetricsEndpoint": "http://localhost:4318/v1/metrics",
"SamplingProbability": 1.0
}
}
For Grafana Cloud, use separate endpoints and auth headers for traces and metrics:
{
"OpenTelemetry": {
"Enabled": true,
"ApplicationName": "my-app",
"OtlpEndpoint": "https://otlp-gateway-prod-eu-west-2.grafana.net/otlp/v1/traces",
"OtlpHeaders": "Authorization=Basic <base64(gatewayInstanceId:apiToken)>",
"OtlpMetricsEndpoint": "https://prometheus-prod-xx-prod-eu-west-2.grafana.net/otlp/v1/metrics",
"OtlpMetricsHeaders": "Authorization=Basic <base64(prometheusInstanceId:apiToken)>",
"SamplingProbability": 0.1
}
}
2. Server — Program.cs
var builder = WebApplication.CreateBuilder(args);
// Razor components (Blazor Server + WASM host)
builder.Services
.AddRazorComponents()
.AddInteractiveServerComponents()
.AddInteractiveWebAssemblyComponents();
// Web API controllers — creates a span per action, reads X-Blazor-* headers automatically
builder.Services
.AddControllers()
.AddApiObservability();
// Circuit handler + navigation instrumentation
builder.Services.AddBlazorObservability();
// OpenTelemetry pipeline: traces + metrics, reads config from appsettings.json
builder.AddBlazorTelemetry();
// Pyroscope CPU profiler — no-op if native profiler is not loaded
builder.AddBlazorProfiler();
var app = builder.Build();
// ...
app.MapControllers();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(Client._Imports).Assembly);
app.Run();
AddApiObservability() creates a child span for every controller action and reads the X-Blazor-* headers sent by the WASM client automatically.
3. WASM client — Program.cs
// BlazorAmpowering.Client/Program.cs
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services.AddWasmObservability(new Uri(builder.HostEnvironment.BaseAddress));
await builder.Build().RunAsync();
AddWasmObservability registers a named HttpClient ("api") and a default scoped HttpClient, both with the context propagation handler attached.
4. Component instrumentation
Add to _Imports.razor to instrument all components in the project:
@using BlazorAmpowering.Observability.WebAssembly
@inherits WasmInstrumentedComponentBase
WasmInstrumentedComponentBase intercepts all Blazor events (clicks, inputs, form submissions) via IHandleEvent and populates the context before any HttpClient call fires.
Safe during server pre-render — all trace calls are silently ignored when the WASM runtime is not active.
5. Explicit context for lifecycle methods
For HTTP calls made from lifecycle hooks (OnInitializedAsync, OnParametersSetAsync) rather than user events, call TraceRequest() before the call:
@code {
protected override async Task OnInitializedAsync()
{
TraceRequest(); // method name captured automatically
products = await Http.GetFromJsonAsync<List<Product>>("/api/products");
}
private async Task AddProduct()
{
// User events are captured automatically — TraceRequest() is optional
TraceRequest("ProductAdded"); // override the event name if needed
await Http.PostAsJsonAsync("/api/products", newProduct);
}
}
Context headers propagated
| Header | Example | Description |
|---|---|---|
X-Blazor-Mode |
WebAssembly |
Always WebAssembly |
X-Blazor-Page |
/products |
Current page URL |
X-Blazor-Component |
ProductList |
Component type name |
X-Blazor-Method |
AddProductAsync |
C# method originating the call |
X-Blazor-Event |
AddProduct |
Derived event name |
X-Client-Latency-Ms |
42 |
Milliseconds from user event to HTTP send |
Event name derivation strips common affixes automatically:
| Method | Event |
|---|---|
AddProductAsync |
AddProduct |
HandleSubmit |
Submit |
OnSaveClicked |
SaveClicked |
Compatibility
Targets net8.0. Forward-compatible with .NET 9 and 10.
License
Apache 2.0 — Copyright 2026 Gaetan Delpierre
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Microsoft.AspNetCore.Components (>= 8.0.26)
- Microsoft.Extensions.Http (>= 8.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 0 | 5/15/2026 |