Traces, métriques et profiling sans modifier votre code métier. Compatible Blazor Server, WebAssembly, Web API et EF Core — exportation vers Grafana Cloud ou auto-hébergé.
Ce qui est instrumenté
Chaque signal est capturé automatiquement par le middleware ou l'AOP — votre logique applicative reste intacte.
Traces entrantes (ASP.NET Core) et sortantes (HttpClient) avec statut, route et IP client.
Connexion, déconnexion et durée de vie de chaque circuit Blazor Server.
OnInitialized, OnParametersSet, OnAfterRender et événements utilisateur (clics, inputs).
Un span par changement de route — latence perçue par l'utilisateur.
Un span automatique par appel de méthode via Castle DynamicProxy. Aucun attribut, aucune modification.
Castle DynamicProxyGC, thread pool et JIT — métriques .NET exportées en continu vers Prometheus / Mimir.
Chaque requête SQL devient un span enfant avec db.statement, db.name et db.system.
Package séparé · betaPropagation du contexte de trace vers l'API serveur via des headers HTTP standards.
Packages NuGet
Le package principal est stable. L'instrumentation EF Core est en beta car sa dépendance OpenTelemetry n'est pas encore stable.
Instrumentation principale : traces HTTP, circuits SignalR, composants Blazor, navigation, AOP services, métriques runtime, profiling Pyroscope.
Voir sur NuGetAjoute un span OpenTelemetry pour chaque requête SQL exécutée par EF Core. En beta car dépend de OpenTelemetry.Instrumentation.EntityFrameworkCore (pre-release).
Voir sur NuGetPropagation du contexte OTel depuis le client WebAssembly vers l'API serveur via des headers HTTP (traceparent, X-Blazor-*).
Voir sur NuGetGuide d'installation
Suivez les étapes correspondant à votre type de projet.
Ajoutez le package NuGet à votre projet serveur.
shelldotnet add package BlazorAmpowering.Observability
Ajoutez la section OpenTelemetry à votre fichier de configuration.
{
"OpenTelemetry": {
"Enabled": true,
"ApplicationName": "my-app",
"OtlpEndpoint": "http://localhost:4318/v1/traces",
"SamplingProbability": 1.0
}
}
Appelez les extensions dans l'ordre indiqué.
Program.csvar builder = WebApplication.CreateBuilder(args);
builder.Services
.AddRazorComponents()
.AddInteractiveServerComponents();
// Web API — un span par action
builder.Services
.AddControllers()
.AddApiObservability();
// Circuit handler + navigation
builder.Services.AddBlazorObservability();
// Pipeline OTel : traces + métriques
builder.AddBlazorTelemetry();
// Profiling Pyroscope (no-op si le profiler natif n'est pas chargé)
builder.AddBlazorProfiler();
Ajoutez l'héritage dans _Imports.razor pour instrumenter tous les composants d'un dossier.
@using BlazorAmpowering.Observability.Components
@inherits InstrumentedComponentBase
OnInitializedAsync par OnInitializedCoreAsync et OnParametersSetAsync par OnParametersSetCoreAsync dans vos composants.@code {
protected override async Task OnInitializedCoreAsync()
{
data = await MyService.GetDataAsync();
}
}
Injectez NavigationInstrumentation dans MainLayout.razor pour tracer chaque changement de route.
@using BlazorAmpowering.Observability.Services
@inject NavigationInstrumentation NavInstrumentation
Ajoutez le package au projet client WebAssembly.
shelldotnet add package BlazorAmpowering.Observability.WebAssembly
Une seule ligne dans le Program.cs du client WASM.
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services.AddWasmObservability();
await builder.Build().RunAsync();
Utilisez WasmInstrumentedComponentBase à la place du base class standard.
@using BlazorAmpowering.Observability.WebAssembly.Components
@inherits WasmInstrumentedComponentBase
MyWasmComponent.razor
@code {
protected override async Task OnInitializedCoreAsync()
{
// Les appels HTTP sortants injectent automatiquement
// traceparent et X-Blazor-* dans les headers.
data = await Http.GetFromJsonAsync<MyData[]>("/api/data");
}
// Contexte explicite pour les appels déclenchés par un événement
private async Task HandleClick()
{
await TraceRequest(() => Http.PostAsJsonAsync("/api/action", payload));
}
}
Chaînez AddApiObservability() après AddControllers().
builder.Services
.AddControllers()
.AddApiObservability();
// Désactiver la capture des paramètres en production (données sensibles)
builder.Services
.AddControllers()
.AddApiObservability(options =>
{
options.CaptureActionParameters = false;
});
Quand l'API est appelée depuis un client WASM, les spans sont automatiquement enrichis avec blazor.component, blazor.method, blazor.event et client.latency_ms.
Exemple de span produitProductsController.GetAll
├─ controller: Products
├─ action: GetAll
├─ http.method: GET
├─ http.route: api/products
├─ http.status_code: 200
├─ blazor.component: ProductList ← injecté par le client WASM
├─ blazor.method: OnInitialized
└─ client.latency_ms: 42
Ce package est en pre-release car sa dépendance OpenTelemetry ne l'est pas encore.
shelldotnet add package BlazorAmpowering.Observability --version 1.0.0
dotnet add package BlazorAmpowering.Observability.EntityFrameworkCore --prerelease
Ajoutez l'instrumentation EF Core après le pipeline OTel principal.
Program.csbuilder.AddBlazorTelemetry();
// EF Core — un span par requête SQL
builder.AddEntityFrameworkCoreInstrumentation();
builder.AddEntityFrameworkCoreInstrumentation(setDbStatementForText: false)GET /api/products
└─ ProductsController.GetAll
└─ SELECT * FROM "Products" ← span EF Core
├─ db.system: sqlite
├─ db.name: mydb
└─ db.statement: SELECT "p"."Id", "p"."Date" FROM "Products" AS "p"
Grafana Cloud
Grafana Cloud fournit Tempo (traces), Mimir/Prometheus (métriques) et Pyroscope (profiling) en service managé.
Dans Grafana Cloud, allez dans Home → My Stack, puis sélectionnez chaque service pour obtenir son endpoint OTLP et son instance ID.
OtlpHeaders pour Tempo et OtlpMetricsHeaders pour Prometheus.{
"OpenTelemetry": {
"Enabled": true,
"ApplicationName": "my-app",
"OtlpEndpoint": "https://otlp-gateway-prod-eu-west-2.grafana.net/otlp/v1/traces",
"OtlpHeaders": "Authorization=Basic <base64(tempoInstanceId:apiToken)>",
"OtlpMetricsEndpoint": "https://prometheus-prod-xx-prod-eu-west-2.grafana.net/otlp/v1/metrics",
"OtlpMetricsHeaders": "Authorization=Basic <base64(prometheusInstanceId:apiToken)>",
"SamplingProbability": 0.1
}
}
Sur Linux, définissez les variables d'environnement suivantes avant de lancer votre application. Sur Windows et macOS, utilisez les scripts fournis dans le package NuGet sous scripts/.
Scripts inclus dans le package :
scripts/run-with-profiling-windows.ps1scripts/run-with-profiling-macos.shscripts/run-with-profiling-linux.shexport CORECLR_ENABLE_PROFILING=1
export CORECLR_PROFILER={BD1A650D-AC5D-4896-B64F-D6FA25D6B26A}
export CORECLR_PROFILER_PATH=./profiler/Pyroscope.Profiler.Native.so
export PYROSCOPE_APPLICATION_NAME=my-app
export PYROSCOPE_SERVER_ADDRESS=https://profiles-prod-XXX.grafana.net
export PYROSCOPE_BASIC_AUTH_USER=<pyroscopeInstanceId>
export PYROSCOPE_BASIC_AUTH_PASSWORD=<apiToken>
dotnet run --project MyApp.csproj
Démarrez la stack locale avec Docker Compose.
shellcd observability
docker compose up -d
| Service | URL |
|---|---|
| Grafana | http://localhost:3000 |
| Prometheus | http://localhost:9090 |
| Tempo | http://localhost:3200 |
| OTel Collector (OTLP HTTP) | http://localhost:4318 |
| Pyroscope | http://localhost:4040 |
Bientôt disponible
Un plugin Grafana et un service SAAS vont transformer vos traces en insights actionnables — directement dans votre dashboard.
Visualisez les lignes de code réellement exécutées en production, ligne par ligne, à partir des traces OpenTelemetry.
Identifiez automatiquement les méthodes et branches jamais appelées en production pour guider vos refactorisations.
Recommandations d'optimisation basées sur l'analyse des spans : N+1, allocations inutiles, hot paths.
Tous ces insights directement dans votre Grafana existant — pas de nouvelle UI à apprendre.
Le service SAAS est en cours de développement. Inscrivez-vous pour être parmi les premiers à y accéder et influencer la roadmap.
Une question, un bug ou une suggestion ? Ouvrez une demande de support — nous répondons en général sous 48 h.