Ch. 8 · Spring Boot

Spring Boot Distributed Tracing

Propagate trace context with Micrometer Tracing, correlate spans across services, and sample without overwhelming storage.

~2 min readadvancedupdated Oct 5, 2026

A distributed trace follows one request across services, joining the spans each service records into a single timeline. Micrometer Tracing integrates with OpenTelemetry or Brave to create and propagate trace context, which is the key to correlating work across a call chain.

Before you start

You should understand spans, traces and basic observability. This article covers tracing in Spring Boot.

Step-by-step walkthrough

Step 1: Instrument automatically

Adding the tracing bridge and an exporter lets Spring create spans for incoming requests, outbound HTTP calls and database queries automatically. Each span records timing and status, and spans share a trace id, so a slow hop is visible.

Step 2: Propagate context across boundaries

The trace id must travel with the request, usually in a traceparent header, so the next service continues the same trace. HTTP clients and messaging need propagation configured; a missing propagation breaks the trace at that hop, and the chain splits.

Step 3: Sample deliberately

Tracing every request is expensive to store, so sampling captures a fraction while keeping errors. A common approach is head sampling at a low rate plus always capturing errors, or tail sampling that keeps slow and failed traces. Choose so that enough traces exist to debug without flooding storage.

Worked scenario

The dependency adds tracing with an exporter.

<dependency>
  <groupId>io.micrometer</groupId>
  <artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
  <groupId>io.opentelemetry</groupId>
  <artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
xml

Walk through the example

The bridge creates spans and the exporter ships them to a collector. Incoming requests get a span, and outbound calls get child spans with propagation headers. Custom spans can wrap business operations so the trace shows where time goes. Sampling then bounds what is stored.

Common mistake

Tracing without propagating context, so each service starts a new trace and the chain is broken. Another is tracing 100% of traffic in production, which overwhelms storage and cost. Adding spans without meaningful names or attributes makes traces hard to read.

Verify the behavior

Make a request across services and confirm a single trace id spans them. Check that child spans appear for outbound calls. Confirm the sampler keeps a configured fraction and always keeps errors.

Interview exercise

What breaks a distributed trace?

Answer and reasoning

A missing or dropped propagation header at a boundary, because the next service then has no parent context and starts a new trace. HTTP clients, messaging and third-party calls all need propagation configured. When it breaks, the chain splits and you see separate traces instead of one timeline.

Continue learning

Compare context in Distributed tracing and metrics in Metrics cardinality. Read the Micrometer Tracing documentation and try the Spring Boot interview questions.

More in Spring Boot

read ✓Spring Boot · hard

Spring @Async and Executor Configuration

Run methods asynchronously with @Async, configure a bounded executor, and handle exceptions and the proxy boundary.

~2 min readread →
read ✓Spring Boot · hard

Spring Boot Caching Abstraction

Cache method results with @Cacheable, choose keys and TTLs, and evict on writes without the self-invocation trap.

~2 min readread →
read ✓Spring Boot · hard

Spring Declarative HTTP Clients

Define outbound HTTP as an annotated interface with @HttpExchange, create the proxy, and configure timeouts and errors.

~2 min readread →
esc