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
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="BlazorAmpowering.Observability.WebAssembly" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BlazorAmpowering.Observability.WebAssembly" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="BlazorAmpowering.Observability.WebAssembly" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add BlazorAmpowering.Observability.WebAssembly --version 1.0.0
                    
#r "nuget: BlazorAmpowering.Observability.WebAssembly, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package BlazorAmpowering.Observability.WebAssembly@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=BlazorAmpowering.Observability.WebAssembly&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=BlazorAmpowering.Observability.WebAssembly&version=1.0.0
                    
Install as a Cake Tool

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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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