Distributed Tracing
Sharkable provides built-in W3C traceparent-compliant distributed tracing with zero external dependencies. OpenTelemetry exporters (Jaeger, Zipkin, OTLP) hook in automatically when installed.
Quick Start
builder.Services.AddShark(opt =>
{
opt.ConfigureTracing(t =>
{
t.ServiceName = "order-api";
});
});
var app = builder.Build();
app.UseShark();
Every request now creates a traceparent-compliant span. The X-Trace-Id header is added to all responses.
How It Works
- Request arrives → middleware creates an
Activity(W3C span) traceparentpropagation → incomingtraceparentheader is inherited; if absent, a new root trace is generated- Tagging → HTTP method, path, host, client IP, status code, duration
- Exception recording → unhandled exceptions set
ActivityStatusCode.Error+ exception tags - Response →
X-Trace-Idheader appended
Zero Dependencies
The tracing middleware uses only System.Diagnostics.ActivitySource and System.Diagnostics.Activity — built into .NET runtime. No NuGet packages required.
OpenTelemetry Integration
Install the OpenTelemetry SDK (separate NuGet packages) and configure it to listen to Sharkable's ActivitySource:
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Exporter.Console # or Jaeger/Zipkin/OTLP
// Program.cs — after AddShark()
builder.Services.AddOpenTelemetry()
.WithTracing(t => t
.AddSource("Sharkable") // Sharkable's ActivitySource name
.AddConsoleExporter() // or AddJaegerExporter(...)
);
The ActivitySource name is exposed as a constant:
TracingMiddleware.ActivitySourceName // "Sharkable"
Pluggable Exporter Interface
For custom exporters or NuGet plugins, implement ITracingExporter:
public interface ITracingExporter
{
void OnActivityStarted(Activity activity);
void OnActivityStopped(Activity activity);
}
builder.Services.AddShark(opt =>
{
opt.ConfigureTracing(t =>
{
t.Exporter = new MyCustomExporter();
});
});
A future Sharkable.OpenTelemetry NuGet package will provide pre-built Jaeger/Zipkin/OTLP exporters.
Configuration
opt.ConfigureTracing(t =>
{
// Service name reported in traces. Default: entry assembly name.
t.ServiceName = "order-api";
// Custom exporter (optional). Default: no-op (OTel SDK hooks automatically).
t.Exporter = new MyCustomExporter();
});