Implement Distributed Tracing in .NET 8 with OpenTelemetry, Azure Monitor, and Jaeger

Mahmut Sarıkaya 3 dk okuma 15 Görüntülenme 0
Implement Distributed Tracing in .NET 8 with OpenTelemetry, Azure Monitor, and Jaeger

Why Distributed Tracing Matters in Modern .NET 8 Applications

When a single request travels through micro‑services, databases, and external APIs, pinpointing latency spikes becomes a guessing game. A 2023 survey by the Cloud Native Computing Foundation reported that 68% of developers consider observability a top‑priority, yet only 32% feel confident about their tracing strategy. In .NET 8, built‑in support for OpenTelemetry turns that uncertainty into actionable insight.

Getting Started: Prerequisites and Packages

Before writing code, verify that you have .NET 8 SDK (version 8.0.100 or later) and Docker Engine installed. The following commands create a minimal Web API project and add the required NuGet packages.

dotnet new webapi -n TracingDemo cd TracingDemo dotnet add package OpenTelemetry.Extensions.Hosting dotnet add package OpenTelemetry.Instrumentation.AspNetCore dotnet add package OpenTelemetry.Exporter.Jaeger dotnet add package OpenTelemetry.Exporter.AzureMonitor

Configuring OpenTelemetry SDK for .NET 8

OpenTelemetry is wired through the generic host. The snippet below registers ASP.NET Core instrumentation, sets a service name, and attaches both Jaeger and Azure Monitor exporters. Notice the use of builder.Configuration[\"AzureMonitor:ConnectionString\"] – store the connection string securely in appsettings.json or Azure Key Vault.

using OpenTelemetry.Trace; using OpenTelemetry.Resources; var builder = WebApplication.CreateBuilder(args); builder.Services.AddOpenTelemetryTracing(telemetryBuilder => { telemetryBuilder .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(\"TracingDemo\")) .AddAspNetCoreInstrumentation() .AddJaegerExporter(jaegerOptions => { jaegerOptions.AgentHost = \"localhost\"; jaegerOptions.AgentPort = 6831; }) .AddAzureMonitorTraceExporter(azureOptions => { azureOptions.ConnectionString = builder.Configuration[\"AzureMonitor:ConnectionString\"]; }); }); var app = builder.Build(); app.MapGet(\"/weatherforecast\", () => { return Enumerable.Range(1,5).Select(index => new { Date = DateTime.Now.AddDays(index), TemperatureC = Random.Shared.Next(-20,55), Summary = \"Sample\" }); }); app.Run();

Sending Traces to Jaeger

Jaeger runs as a single Docker container for local development. The command below starts the all‑in‑one image, exposing the UI on port 16686 and the collector on 14250. Once the API is running, open http://localhost:16686 to explore spans generated by the sample endpoint.

docker run -d --name jaeger \\ -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \\ -p 16686:16686 -p 14250:14250 -p 9411:9411 \\ jaegertracing/all-in-one:1.50

Integrating Azure Monitor for Cloud‑Scale Insights

Azure Monitor aggregates traces from all instances of your service, correlates them with logs, and applies intelligent sampling. After publishing the app to Azure App Service, enable “Application Insights” and paste the same connection string used in the code. The exporter respects the OTEL_EXPORTER_AZUREMONITOR_SAMPLE_RATE environment variable, allowing you to cap ingestion at, for example, 10 % of requests.

Testing the End‑to‑End Flow

Run the API locally with dotnet run, then invoke the endpoint ten times using curl or a browser. In Jaeger’s UI you will see a trace per request, each containing an ASP.NET Core span and an automatic HTTP client span (if you add outgoing calls). Switch to Azure Monitor’s “Transaction search” view to verify that the same trace IDs appear, proving that both exporters share the OpenTelemetry context.

Performance Tips and Common Pitfalls

1. **Sampling strategy** – Unlimited sampling can double CPU usage on high‑traffic services. Start with AlwaysOnSampler for dev, then move to ParentBasedSampler with a 0.1 (10 %) rate in production.
2. **Resource naming** – Use consistent service names across exporters; otherwise you will see duplicate entries in Azure Monitor.
3. **Network latency** – Jaeger exporter uses UDP; ensure the agent host is reachable from your container. For cloud deployments, consider the Jaeger collector over HTTP to avoid packet loss.

Conclusion

By coupling .NET 8’s native OpenTelemetry support with Jaeger for local debugging and Azure Monitor for enterprise‑scale analytics, you gain end‑to‑end visibility without rewriting business logic. The configuration fits into the standard host builder, so adding or removing exporters is a matter of a few lines. Adopt the sample code, tune sampling, and let distributed tracing become a proactive part of your CI/CD pipeline.

Sources

  • OpenTelemetry .NET Documentation
  • Azure Monitor Exporter Guide
  • Jaeger Tracing Quickstart

Author: Mahmut Sarıkaya — sarikayadev.com

Etiketler: #.NET 8 #OpenTelemetry #Distributed Tracing #Azure Monitor #Jaeger
Paylaş:
M

Yazar

Mahmut Sarıkaya

yazılım Geliştirici

Yorumlar

Henüz yorum yok. İlk yorumu siz yapın!

Yorum Bırakın

5 + 3 =