skip to content

Micrometer Tracing Bridges (OTel/Brave)

Micrometer Tracing is an abstraction bridged to OpenTelemetry or Brave, managing span and scope lifecycles and exporting to Zipkin or an OTLP collector. Interviewers ask which backend you used and whether you understood the bridge in between.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What is Micrometer Tracing, and what does a 'tracing bridge' (bridge-otel / bridge-brave) actually do?

level: juniorimportance: must knowfreq 62%

answer

  1. facade + one bridge JAR = tracer choice
  2. bridge-otel = OpenTelemetry, bridge-brave = Brave/Zipkin
  3. replaced Spring Cloud Sleuth in Boot 3
  4. bridge != exporter
  5. code imports only Micrometer types

basics

~20 s

Micrometer Tracing is a vendor-neutral facade for distributed tracing. A bridge plugs a real tracer (OpenTelemetry or Brave/Zipkin) behind that facade, so your code uses one API while the bridge does the actual span work.

solid answer

~40 s

Micrometer Tracing is the tracing facade that replaced Spring Cloud Sleuth in Spring Boot 3. Your code depends only on its neutral API — the Tracer, Span, and SpanInScope abstractions. It does no tracing itself; it delegates to a concrete tracer chosen by which bridge JAR is on the classpath. Add micrometer-tracing-bridge-otel and you get OpenTelemetry as the SDK; add micrometer-tracing-bridge-brave and you get Brave (the OpenZipkin library). You pick exactly one bridge. The bridge translates Micrometer's Span/TraceContext calls into that library's objects, and a separate exporter dependency ships the finished spans to a backend such as Zipkin or an OTLP collector. This lets you swap tracer implementations without touching application code.

code

java · 23 lines
java
// build.gradle — facade + ONE bridge + ONE exporter
// implementation 'org.springframework.boot:spring-boot-starter-actuator'
// implementation 'io.micrometer:micrometer-tracing-bridge-otel'   // choose OTel...
// implementation 'io.opentelemetry:opentelemetry-exporter-otlp'   // ...and OTLP export

// Application code depends ONLY on the Micrometer facade:
import io.micrometer.tracing.Tracer;
import io.micrometer.tracing.Span;

@Service
class PricingService {
    private final Tracer tracer; // injected; impl comes from the bridge
    PricingService(Tracer tracer) { this.tracer = tracer; }

    void price() {
        Span span = tracer.nextSpan().name("price");
        try (Tracer.SpanInScope scope = tracer.withSpan(span.start())) {
            span.tag("tier", "gold");
        } finally {
            span.end();
        }
    }
}

go deeper

for a junior

Know it's a facade + a bridge picks the real tracer (OTel or Brave); replaced Sleuth.

for a middle

Distinguish bridge from exporter; know the two bridge artifacts and matching exporters.

for a senior

Explain Observation→span integration and that only sampled spans export while ids always propagate.

for a principal

Reason about migration from Sleuth/Brave to OTel, standardization on OTLP, and ecosystem trade-offs.

## The problem it solves **Distributed tracing** records the path of one request as it hops across services. Each unit of work is a **span** (an operation with a start time, duration, name, tags, and events); spans sharing a **trace id** form one **trace**. To make this work you need a library that creates spans, propagates ids across network calls, samples, and exports to a backend. Historically Spring used **Spring Cloud Sleuth**, which was tightly coupled to Brave. In **Spring Boot 3+** that was replaced by **Micrometer Tracing**. ## What Micrometer Tracing is Micrometer Tracing is a **facade** — a thin, vendor-neutral API. Its key abstractions: - `io.micrometer.tracing.Tracer` — creates/starts spans and exposes the current span. - `io.micrometer.tracing.Span` — one operation; you `tag(...)`, add `event(...)`, and `end()` it. - `Tracer.SpanInScope` — an `AutoCloseable` that marks a span as *current* on the thread. - `TraceContext` / `Baggage` — the propagated ids and custom key/value context. Critically, the facade contains **no tracing logic**. It needs a concrete implementation supplied at runtime. ## What a bridge does A **bridge** is the adapter that connects the Micrometer facade to a real tracer library. There are two official bridges, and you add **exactly one**: - `io.micrometer:micrometer-tracing-bridge-otel` → backs the facade with the **OpenTelemetry** SDK. Micrometer `Span` calls become OpenTelemetry `io.opentelemetry.api.trace.Span` calls. - `io.micrometer:micrometer-tracing-bridge-brave` → backs the facade with **Brave** (the OpenZipkin tracer). Micrometer calls become `brave.Span` calls. The bridge is *the choice of tracer implementation*. Your application code never imports OpenTelemetry or Brave types — only Micrometer's — so switching bridges is a dependency change, not a code change. ## The bridge is not the exporter Creating spans and **exporting** them are separate concerns. The bridge produces spans in the chosen library's format; a separate **exporter/reporter** dependency ships them: - Brave bridge → `io.zipkin.reporter2:zipkin-reporter-brave` sends to **Zipkin**. - OTel bridge → `io.opentelemetry:opentelemetry-exporter-zipkin` (to Zipkin) or `opentelemetry-exporter-otlp` (to an **OTLP** collector). Spring Boot auto-configures the exporter when its endpoint property (`management.zipkin.tracing.endpoint` or `management.otlp.tracing.endpoint`) is present. ## Auto-configuration in Spring Boot With `spring-boot-starter-actuator` plus a bridge plus an exporter, Boot's `TracingAutoConfiguration` and bridge-specific auto-config wire a `Tracer`, propagators, and the exporter. Tracing also integrates with **Micrometer Observation**: every `Observation` (HTTP server/client, `@Observed`, scheduled tasks) automatically opens and closes a span via `DefaultTracingObservationHandler`, so you often get traces without writing span code at all. ## When to use which - **OTel bridge** is the modern default: OpenTelemetry is the CNCF standard, supports OTLP natively, and has the broadest ecosystem. - **Brave bridge** suits shops already standardized on Zipkin/Brave or needing a specific Brave feature. ## Gotchas - Adding **both** bridges is a misconfiguration — pick one. - A bridge with **no exporter** still creates spans and propagates context but sends nothing to a backend. - Only **sampled** spans are exported; ids are still propagated for unsampled traces.

  • What replaced Spring Cloud Sleuth, and why the change?
    Micrometer Tracing replaced Sleuth in Spring Boot 3. Sleuth was Brave-coupled and tied to the Spring Cloud release train; Micrometer Tracing is a neutral facade with swappable bridges (OTel or Brave), aligning tracing with the Micrometer Observation API.
  • If you add a bridge but no exporter dependency, what happens?
    Spans are still created and trace context is still propagated across calls (and shows up in MDC/logs), but nothing is shipped to a backend like Zipkin — you get correlation ids in logs but no trace UI.

saying these in an interview costs you the question

  • Thinking Micrometer Tracing itself creates/exports spans without a bridge
  • Adding both bridge-otel and bridge-brave at once
  • Believing the bridge also exports (confusing bridge with the exporter dependency)
  • Claiming Spring Cloud Sleuth is still the Boot 3 tracing library

context

open as a page

Walk through the manual span/scope lifecycle with the Micrometer Tracer API. Why must you close the scope AND end the span, and what breaks if you don't?

level: seniorimportance: must knowfreq 55%

basics

~20 s

Create a span (tracer.nextSpan().name(...)), start it, open a scope with tracer.withSpan(span) so it becomes 'current', do work, then close the scope (try-with-resources) and call span.end(). Skipping end() loses timing/export; leaving a scope open leaks context onto later work on that thread.

open as a page

How do you choose between the OpenTelemetry bridge and the Brave bridge, and what dependencies pair with each for Zipkin vs OTLP export?

level: middleimportance: should knowfreq 48%

basics

~10 s

Pick one bridge. OTel bridge (micrometer-tracing-bridge-otel) is the modern default and exports via OTLP or Zipkin. Brave bridge (micrometer-tracing-bridge-brave) exports to Zipkin via zipkin-reporter-brave. Never add both.

open as a page

How does Micrometer Tracing hook into the Observation API so Spring MVC/WebClient calls get spans automatically, and how does context propagate to a downstream service?

level: seniorimportance: should knowfreq 42%

basics

~20 s

Spring instruments HTTP and other work as Observations. Tracing registers ObservationHandlers that turn each Observation into a span. For outbound calls a propagating handler injects trace headers; on the server side another handler extracts them, so the downstream span joins the same trace.

open as a page

In production, sampling probability is 0.1 and users report 'traces are missing.' Explain how sampling, context propagation, and the exporter interact, and what you'd verify.

level: principalimportance: should knowfreq 33%

basics

~20 s

At 0.1 only ~10% of traces are exported by design — that's expected, not a bug. The sampling decision is made once at the trace root and propagated downstream, so all services agree. Verify the endpoint, that ids still appear in logs (proving propagation works), and consider raising probability or using tail sampling in the collector.

open as a page