Skip to content

Trace Context

Understanding Trace Context

Trace context is the mechanism that enables distributed tracing systems to correlate spans across service boundaries. In a microservices architecture, where requests traverse multiple services, trace context headers ensure that all components of a single request share the same trace ID and span ID, allowing end-to-end visibility. Without proper trace context propagation, traces would fragment, making debugging and performance analysis infeasible.

Modern systems rely on standardized headers like W3C TraceContext (RFC 9514) and legacy headers like B3 (from the Zipkin project) to carry trace metadata. OpenTelemetry supports both, but W3C is the recommended standard due to its broader compatibility and extensibility.


W3C TraceContext Headers

The W3C TraceContext standard defines two key headers:

traceparent

This header contains the core trace context information: - Trace ID: A 64-bit hexadecimal string (e.g., 123e4567e89b12d3a456c78901234567) - Span ID: A 64-bit hexadecimal string (e.g., 123e4567e89b12d3) - Trace Flags: Indicates if the trace is sampled (01 for sampled, 00 for not sampled) - Debug Flag: Optional, used for debugging (not part of the standard)

Example:

traceparent: 123e4567e89b12d3a456c78901234567-123e4567e89b12d3-01

tracestate

This header carries vendor-specific or custom data (e.g., baggage for OpenTelemetry). It is a semicolon-separated list of key-value pairs:

tracestate: baggage=abc123;vendor=xyz456


B3 Headers (Legacy)

B3 headers are used in older systems and are less standardized. They include: - traceid (128-bit hex) - spanid (64-bit hex) - flags (sampled or not) - baggage (custom metadata)

Example:

traceid: 123e4567e89b12d3a456c78901234567
spanid: 123e4567e89b12d3
flags: 1
baggage: abc123

While B3 is still used in some environments, W3C is preferred for new systems due to its extensibility and support for multiple tracing backends.


Propagation in OpenTelemetry

OpenTelemetry SDKs automatically inject and extract trace context headers when making HTTP requests. By default, it uses W3C headers, but you can configure it to use B3 if needed.

Example: Injecting Headers with OpenTelemetry

from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

trace.set_tracer_provider(TracerProvider())
trace.get_tracer_provider().add_span_processor(
    BatchSpanProcessor(OTLPSpanExporter())
)

tracer = trace.get_tracer(__name__)

with tracer.start_as_current_span("example-span") as span:
    # HTTP request will automatically include traceparent and tracestate headers
    pass

Example: Extracting Headers in a Server

// Java (Spring Boot)
@RestController
public class TraceController {
    @GetMapping("/trace")
    public ResponseEntity<String> trace() {
        Span span = Span.current();
        String traceId = span.getSpanContext().getTraceId();
        String spanId = span.getSpanContext().getSpanId();
        return ResponseEntity.ok("Trace ID: " + traceId + ", Span ID: " + spanId);
    }
}

Implementation Considerations

  1. Header Compatibility: Ensure all services in your ecosystem support the same trace context format (prefer W3C).
  2. Sampling: Use trace flags to control whether traces are sampled (reduces data volume).
  3. Tracestate Extensibility: Leverage tracestate for vendor-specific metadata (e.g., baggage for OpenTelemetry).
  4. Header Injection: Always inject trace context headers in outgoing requests (e.g., HTTP clients, messaging systems).

Key takeaways

  • Trace context headers (W3C/B3) are essential for correlating spans across services.
  • W3C TraceContext is the modern standard, offering better extensibility and compatibility.
  • OpenTelemetry SDKs automatically handle header injection/extractioN when configured properly.
  • Always validate that all services in your system propagate trace context headers consistently.