How do you choose between the OpenTelemetry bridge and the Brave bridge, and what dependencies pair with each for Zipkin vs OTLP export?
answer
- one bridge, matching exporter
- otel → OTLP or zipkin exporter; brave → zipkin-reporter-brave
- OTLP path /v1/traces, Zipkin /api/v2/spans
- OTel default W3C traceparent, Brave default B3
- management.otlp/zipkin.tracing.endpoint
basics
~10 sPick 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.
solid answer
~40 sYou add exactly one bridge, and the exporter must match it. For OpenTelemetry, use micrometer-tracing-bridge-otel with either opentelemetry-exporter-otlp (to an OTLP collector — Tempo, Jaeger, the OTel Collector) or opentelemetry-exporter-zipkin (to Zipkin). For Brave, use micrometer-tracing-bridge-brave with zipkin-reporter-brave (to Zipkin). Choose OTel when you want the CNCF standard, native OTLP, and the widest backend support — it's the default recommendation. Choose Brave if you're already invested in Zipkin/Brave tooling. Spring Boot auto-configures the exporter from properties: management.otlp.tracing.endpoint for OTLP and management.zipkin.tracing.endpoint for Zipkin. Sampling is controlled by management.tracing.sampling.probability regardless of bridge. Mixing bridges, or an OTel exporter with the Brave bridge, is a misconfiguration.
code
java · 14 lines// OTel bridge + OTLP (recommended modern setup)
// build.gradle:
// implementation 'io.micrometer:micrometer-tracing-bridge-otel'
// implementation 'io.opentelemetry:opentelemetry-exporter-otlp'
// application.properties:
// management.tracing.sampling.probability=0.1
// management.otlp.tracing.endpoint=http://otel-collector:4318/v1/traces
// management.tracing.propagation.type=W3C
// ---- OR: Brave bridge + Zipkin ----
// implementation 'io.micrometer:micrometer-tracing-bridge-brave'
// implementation 'io.zipkin.reporter2:zipkin-reporter-brave'
// management.zipkin.tracing.endpoint=http://zipkin:9411/api/v2/spansgo deeper
Know there are two bridges and you pick one; OTel is the modern default.
Map each bridge to its compatible exporter and endpoint property; know W3C vs B3 defaults.
Advise migrations (OTel bridge + Zipkin exporter) and enforce a single propagation format fleet-wide.
Set org tracing strategy: OTLP+Collector standardization, backend portability, correlation with OTel logs/metrics.
## The two decisions Setting up tracing is really two independent choices: **which bridge** (tracer implementation) and **which exporter** (wire format + backend). They must be compatible. ## Choice 1 — the bridge ### OpenTelemetry bridge — `io.micrometer:micrometer-tracing-bridge-otel` Backs Micrometer with the **OpenTelemetry SDK**. Pros: - **OTLP** (OpenTelemetry Protocol) is a first-class citizen — the standard collector protocol. - Broadest backend support: Grafana Tempo, Jaeger, the OpenTelemetry Collector, most vendors. - CNCF standard; aligns with OTel metrics/logs if you go all-in on OTel. ### Brave bridge — `io.micrometer:micrometer-tracing-bridge-brave` Backs Micrometer with **Brave** (the OpenZipkin tracer that Sleuth used). Pros: - Mature, battle-tested Zipkin integration. - Natural choice if your org already runs Zipkin and Brave-based instrumentation. **Rule: exactly one bridge on the classpath.** Both together is ambiguous and misconfigures auto-config. ## Choice 2 — the exporter (must match the bridge) | Bridge | Exporter dependency | Ships to | |---|---|---| | bridge-otel | `io.opentelemetry:opentelemetry-exporter-otlp` | OTLP collector (Tempo, Jaeger OTLP, OTel Collector) | | bridge-otel | `io.opentelemetry:opentelemetry-exporter-zipkin` | Zipkin | | bridge-brave | `io.zipkin.reporter2:zipkin-reporter-brave` | Zipkin | An **OTel exporter only works with the OTel bridge**, and `zipkin-reporter-brave` only with the Brave bridge — they consume the tracer library's native span objects. ## Spring Boot properties (bridge-agnostic where possible) ```properties # Sampling — same property for both bridges management.tracing.sampling.probability=1.0 # 1.0 = trace everything (dev) # OTLP export (OTel bridge) management.otlp.tracing.endpoint=http://collector:4318/v1/traces # Zipkin export (either bridge, with the matching exporter) management.zipkin.tracing.endpoint=http://zipkin:9411/api/v2/spans ``` Spring Boot's auto-config (`OtlpAutoConfiguration`, `ZipkinAutoConfiguration`) creates the sender/exporter bean when the endpoint property is set. ## Propagation format The bridge also decides default **context-propagation** headers: - OTel bridge defaults to **W3C `traceparent`** (configurable via `management.tracing.propagation.type`, e.g. `W3C`, `B3`). - Brave bridge defaults to **B3** headers (`X-B3-TraceId`, etc.). Mismatched propagation across services breaks trace continuity — standardize the format fleet-wide. ## Decision guidance - **New systems / vendor-neutral / OTLP** → OTel bridge. This is the recommended default. - **Existing Zipkin+Brave estate** → Brave bridge (or OTel bridge + Zipkin exporter to keep Zipkin while modernizing the tracer). - Need OTel **logs/metrics correlation** too → OTel bridge. ## Gotchas - Endpoint path differs: OTLP HTTP is `/v1/traces`; Zipkin is `/api/v2/spans`. - `sampling.probability` too low in prod means most traces never export (by design), which can look like 'tracing is broken'. - Grafana Tempo and Jaeger both accept OTLP, so OTel bridge + OTLP covers them without Zipkin.
- Can you use the OTel bridge but still export to Zipkin?Yes. Use micrometer-tracing-bridge-otel with opentelemetry-exporter-zipkin and set management.zipkin.tracing.endpoint. This keeps Zipkin as backend while running the OpenTelemetry SDK as the tracer — a common migration step off Brave.
- Two services can't stitch traces together though headers flow. What's a likely cause?Propagation-format mismatch: one service emits W3C traceparent (OTel default) and the other expects B3 (Brave default). Align management.tracing.propagation.type across services so both read the same headers.
saying these in an interview costs you the question
- Pairing zipkin-reporter-brave with the OTel bridge (or an OTel exporter with the Brave bridge)
- Thinking OTLP can only go to Jaeger, or that Zipkin needs Brave
- Adding both bridges 'to be safe'
- Assuming propagation headers are identical across bridges