skip to content

What is distributed tracing, and what are trace IDs and span IDs in a Spring Boot application using Micrometer Tracing (formerly Spring Cloud Sleuth)?

level: juniorimportance: must knowfreq 70%

answer

  1. trace ID = whole request, span ID = one step
  2. Sleuth -> Micrometer Tracing (Boot 3)
  3. IDs pushed into MDC -> logs
  4. [appName,traceId,spanId] log pattern
  5. propagate + export to Zipkin

basics

~20 s

Distributed tracing follows one request as it hops between services. A trace ID is a shared id for the whole request; a span id marks one step (like one service call). Micrometer Tracing adds both to logs automatically.

solid answer

~40 s

Distributed tracing lets you follow a single request end-to-end as it crosses multiple services. Micrometer Tracing (the successor to Spring Cloud Sleuth) assigns each incoming request a trace ID that stays constant across every service it touches, and a span ID for each individual unit of work (an HTTP call, a DB query). Spans form a parent-child tree, so you can see who called whom and how long each step took. With the right dependencies on the classpath, Spring Boot auto-configures this: it injects trace and span IDs into your logs via MDC and can export the timing data to a backend like Zipkin. This turns a pile of disconnected logs across services into one correlated timeline you can search by trace ID.

code

java · 18 lines
java
// build.gradle dependencies (Spring Boot 3)
// implementation 'org.springframework.boot:spring-boot-starter-actuator'
// implementation 'io.micrometer:micrometer-tracing-bridge-brave'
// implementation 'io.zipkin.reporter2:zipkin-reporter-brave'

@RestController
class OrderController {
    private static final Logger log = LoggerFactory.getLogger(OrderController.class);

    @GetMapping("/orders/{id}")
    public String get(@PathVariable String id) {
        // No manual work: the trace ID and span ID are already in MDC,
        // so this log line is automatically tagged, e.g.:
        // [order-service,3f1a...,a2b9...] fetching order 42
        log.info("fetching order {}", id);
        return "order-" + id;
    }
}

go deeper

for a junior

Know the trace-ID-vs-span-ID distinction and that Boot auto-adds them to logs.

for a middle

Explain the parent-child span tree and how IDs propagate across HTTP calls.

for a senior

Discuss the Sleuth->Micrometer migration and the bridge/exporter dependency split.

for a principal

Frame tracing as one output of the unified Observation model and reason about org-wide correlation standards.

## The problem In a microservice system, one user action (say, 'place order') fans out into calls across many services: gateway -> order-service -> payment-service -> inventory-service. When something is slow or fails, each service has its own logs, and there is no obvious way to connect them. **Distributed tracing** solves this by tagging every hop of a single request with shared identifiers. ## Core vocabulary - **Trace**: the whole journey of one request through the system. Identified by a **trace ID** (a hex string) that is generated once at the entry point and then propagated unchanged to every downstream service. - **Span**: a single named, timed unit of work within a trace (e.g. 'handle HTTP GET /orders', 'SELECT from orders', 'call payment-service'). Each span has its own **span ID**, a start time, a duration, and a reference to its **parent span ID**. Spans form a tree/DAG describing causality. - **Trace context**: the small bundle of data (trace ID, current span ID, sampling decision) that must travel with the request so downstream services can continue the same trace. ## Micrometer Tracing vs Spring Cloud Sleuth **Spring Cloud Sleuth** was the old (Spring Boot 2.x) library that did this. As of Spring Boot 3, Sleuth is **discontinued and replaced by Micrometer Tracing**, which lives under the Micrometer project and integrates with the **Observation API** (`io.micrometer.observation`). You add Micrometer Tracing plus a **tracer bridge** (Brave or OpenTelemetry) and optionally an exporter (e.g. Zipkin). ## What Spring Boot auto-configures With the dependencies present, Spring Boot's `ObservationAutoConfiguration` and the tracing bridge auto-configuration wire up: 1. An **`ObservationRegistry`** and a **`Tracer`** bean. 2. Automatic instrumentation of common integration points: incoming server requests (`WebMvc`/`WebFlux`), outgoing `RestTemplate`/`WebClient` calls, scheduled tasks, messaging, etc. Each becomes an observation that opens a span. 3. **Log correlation**: trace ID and span ID are pushed into **SLF4J MDC** and appear in your log lines. The default Spring Boot log pattern shows `[appName,traceId,spanId]`. ## A concrete flow 1. A request arrives at the gateway with no trace context. The server instrumentation generates a new trace ID and a root span ID. 2. The gateway calls order-service via `WebClient`. The client instrumentation **injects** the trace context into outbound HTTP headers (W3C `traceparent` or B3 headers). 3. order-service's server instrumentation **extracts** those headers, so it continues the SAME trace ID but creates a new child span. 4. Every service reports its finished spans to a collector (Zipkin), which reassembles them into one waterfall view. ## When to use / not use Use tracing whenever requests cross process boundaries and you need to reason about latency or failures across services. Even in a single service it gives you log correlation per request. The main cost is a small per-request overhead and the need to run a trace backend, which you manage with **sampling** (only recording a fraction of traces). ## Gotchas for a beginner - Trace IDs propagate automatically only across **instrumented** integrations. Raw `java.net.HttpURLConnection` or a manually created thread may drop the context. - If you see IDs in logs but nothing in Zipkin, you likely have the tracing bridge but not the exporter dependency, or sampling is set to 0.

  • How does the trace ID end up in your log lines without you writing any code?
    The tracing instrumentation puts `traceId` and `spanId` into SLF4J's MDC when a span is current, and Spring Boot's default logging pattern includes `[applicationName,traceId,spanId]`, so every log emitted inside that span carries the IDs.
  • What replaced Spring Cloud Sleuth and why?
    Micrometer Tracing replaced it in Spring Boot 3. The instrumentation model was unified under the Micrometer Observation API so a single `Observation` produces both metrics and traces, and Sleuth's separate machinery was retired.

saying these in an interview costs you the question

  • Thinking each service generates its own separate trace ID (defeats correlation — the trace ID must be propagated unchanged).
  • Believing Sleuth is still the current Spring Boot 3 library.
  • Assuming trace IDs appear in Zipkin with only the bridge dependency and no exporter.

context