Advanced · Distribute
Propagate Context Across Service Boundaries
Use Micrometer Observation and OpenTelemetry export to connect request, message, and async work.
Primary source: Spring Cloud 2024 Reference Documentation
Lesson 3 of 4
1d streakThe Architectural Question
Per-service logs cannot reconstruct cross-service latency; without W3C traceparent propagation the story of one slow checkout stays fragmented.
What this guide proves
- Propagate standard trace headers
- Keep baggage small and non-sensitive
- Preserve context across executors and message headers
Distributed Tracing Foundations: W3C Trace Context
In a microservices architecture, a single user click may trigger requests across an API Gateway, an Order Service, an Inventory Service, and a Payment Service. When a request fails or experiences latency, diagnosing the bottleneck without distributed tracing is impossible.
W3C Trace Context standardizes cross-service context propagation via two HTTP headers:
1. traceparent: Encodes version, 16-byte Trace ID (shared across all hops), 8-byte Span ID (representing the current operation), and trace flags.
2. tracestate: Carries vendor-specific tracking metadata across systems.
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
| | | | | |
version |---------------- Trace ID -------| |-- Span ID -----| flagsMicrometer Tracing with OpenTelemetry Exporter
In Spring Boot 3.5, Spring Cloud Sleuth is replaced by Micrometer Tracing. To stream distributed traces to observability backends (Zipkin, Jaeger, Grafana Tempo, Datadog), include micrometer-tracing-bridge-otel and the OpenTelemetry exporter.
management:
tracing:
sampling:
probability: 1.0 # 100% trace sampling in dev/staging; tune in production
otlp:
tracing:
endpoint: http://tempo.internal:4318/v1/tracesBaggage Propagation and MDC Log Correlation
Micrometer Tracing automatically binds the active Trace ID and Span ID into the SLF4J Mapped Diagnostic Context (MDC), ensuring that every log line emitted across any service contains correlation identifiers for centralized aggregation in Loki or Elasticsearch.
Baggage allows propagating custom business metadata (e.g. tenant-id or user-id) transparently across HTTP and Kafka hops without modifying service method signatures.
Inspecting Distributed Trace Waterfalls
Verify end-to-end trace correlation and span waterfalls:
# 1. Send HTTP request and inspect returned traceparent header
curl -i http://localhost:8080/api/orders
# Response headers: traceparent: 00-e2b8...-f4a1...-01
# 2. Inspect application log output:
# 2026-09-07 14:32:01.104 INFO [order-service,e2b8...,f4a1...] c.e.o.OrderController - Created order ORD-101
# 3. Query OpenTelemetry collector / Tempo for Trace ID:
# Verify waterfall display linking Gateway -> OrderService -> Kafka -> PaymentServiceActive Recall Checkpoint
What is the difference between a Trace ID and a Span ID in distributed tracing?
Hint: Think of a tree structure: the tree has one Trace ID; each branch has its own Span ID.
Show answer & explanation
A Trace ID is globally unique and shared by every service hop involved in a single end-to-end user transaction. A Span ID is unique to a specific individual unit of work or service execution within that trace.
Runtime Architecture & Flow
Reliable event flow · runtime visualization
Propagate Context Across Service Boundaries
Local commit
Propagate standard trace headers
Publisher
Keep baggage small and non-sensitive
Broker
Preserve context across executors and message headers
Consumer
Trace checkout through gateway, order service, catalog, and one Kafka event.
Working Implementation
Code Walkthrough
Trace checkout through gateway, order service, catalog, and one Kafka event.
package com.example.tracing;
import io.micrometer.tracing.Baggage;
import io.micrometer.tracing.Span;
import io.micrometer.tracing.Tracer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class DistributedTracingOtelLab {
private static final Logger log = LoggerFactory.getLogger(DistributedTracingOtelLab.class);
private final Tracer tracer;
public DistributedTracingOtelLab(Tracer tracer) {
this.tracer = tracer;
}
public void executeWithTraceCorrelation(String customerId) {
// Set W3C Baggage to propagate customer identifier across downstream microservices
try (Baggage baggage = this.tracer.createBaggageInScope("customer-id", customerId)) {
Span newSpan = this.tracer.nextSpan().name("order-fraud-check").start();
try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan)) {
log.info("Checking fraud score for customer: {}", customerId);
// Log automatically contains traceId and spanId in MDC!
} finally {
newSpan.end();
}
}
}
}Synthesis & Production Verification
Deliberate Failure Condition
- Break: Spawn async work with a plain executor instead of an instrumented one
- Observe: Spans arrive orphaned and the trace ends at the hop that handed off
- Repair: Propagate context through Observation-aware wrappers and message headers, and keep baggage small and free of sensitive values.
Production Acceptance Criteria
- Propagate traceparent across HTTP calls and one Kafka topic
- Preserve trace context across executor handoffs
- Keep baggage minimal and non-sensitive by policy
Key Takeaway
Distributed tracing propagates W3C Traceparent headers across HTTP and Kafka hops, binding Trace and Span IDs into SLF4J MDC for centralized log correlation.
Architectural & Technical Review
Core Interview Questions
Q01What is the format and significance of the W3C traceparent header in distributed tracing?Show answer
traceparent contains four dash-delimited fields: version (00), 16-byte hex Trace ID (global across all hops), 8-byte hex Span ID (unique to this segment), and trace flags (01 for sampled). It enables vendor-neutral tracing.
Q02How does Micrometer Tracing integrate with SLF4J MDC to simplify log analysis?Show answer
Micrometer automatically writes traceId and spanId into the MDC. Standard logging patterns (%X{traceId}, %X{spanId}) include correlation IDs on every log line, allowing developers to query all logs for a transaction in Loki.
Q03How does Baggage differ from standard Trace Context headers in OpenTelemetry?Show answer
Standard trace context propagates only IDs and sampling flags. Baggage propagates arbitrary business key-value pairs (e.g. tenant-id, account-type) across all network hops without modifying method signatures.
Production Pitfalls
Critical Anti-Patterns
- Pitfall: Omitting trace context propagation headers when creating manual HTTP or Kafka requests — Breaks the distributed trace waterfall, creating orphan spans that cannot be linked to the root user request.
- Pitfall: Sampling 100% of traces in high-traffic production environments without rate limits — Generates massive network egress and storage costs on APM observability platforms like Datadog or Tempo.
Primary Documentation & Specifications
Lesson Primary References
Supplementary Module Resources