On this page
Distributed Tracing
After a request spans over a dozen microservices, how do you know where the time was spent? Distributed tracing assigns a trace ID to each request. Cross-service call relationships pass the span context (trace ID + parent span ID + sampling flag) via context propagation, piecing together fragments scattered across nodes into a complete call chain. Sampling strategies are key to cost control: full sampling is too expensive, fixed-ratio sampling misses tail errors, and tail-based sampling decides which traces to retain after completion.
Dapper (Google 2010) → OpenTelemetry
Google's Dapper paper inspired the open-source ecosystem: Zipkin (Twitter) → Jaeger (Uber) → OpenTracing + OpenCensus → OpenTelemetry (CNCF, current standard).
Trace and Span
Context Propagation
Cross-service trace propagation is critical—each service must know "which span of which trace I am":
HTTP: traceparent: 00-<trace_id>-<span_id>-<trace_flags>
W3C Trace Context (standard): traceparent header
gRPC: metadata (grpc-trace-bin)
Kafka: message headers
trace_flags: bit 0 = SAMPLED (whether sampled), other bits reserved.
Internal implementation: The tracer creates a new span (as a child of the caller span) when calling downstream services, placing trace_id + new_span_id into outbound headers. Downstream middleware/libraries (HTTP client, gRPC stub, DB driver) extract the trace context when receiving the response, automatically creating the child span.
Sampling
Full collection → overhead is unacceptable (~1μs overhead per span + network/storage costs). Sampling strategies are needed:
- Head-based (probabilistic): Decide whether to sample at the start of the trace (random 1/100 or 1/1000). Simple, but may miss traces containing errors.
- Tail-based (intelligent): Cache all spans (local buffer), and decide whether to retain them after the trace completes based on the result (ERROR? latency > SLO?). Ensures errors are not lost, but has high memory overhead. OpenTelemetry's
tailsamplingprocessor implements this strategy.
Jaeger Deployment (Reference)
# Agent (one per host, receives spans sent by apps via UDP)
# Collector (central, receives from agents → writes to storage)
# Storage (Cassandra/Elasticsearch)
# Query (UI + API)
References
- Paper: "Dapper, a Large-Scale Distributed Systems Tracing Infrastructure" (Google, 2010)
- OpenTelemetry: opentelemetry.io/docs/specs/otel/trace
- Jaeger: jaegertracing.io
Keywords: distributed tracing, Dapper, OpenTelemetry, Span, trace context propagation, W3C Trace Context, sampling