For the complete documentation index, see llms.txt. This page is also available as Markdown.

Distributed Tracing with Jaeger & OpenTelemetry

Jaeger — Open Source, End-to-End Distributed Tracing

This is the current tracing implementation. The project was migrated from Zipkin + Brave to Jaeger + OpenTelemetry as part of the Spring Boot 3 modernisation. See the legacy Sleuth & Zipkin guide for the old approach.


Why Jaeger over Zipkin?

Both Zipkin and Jaeger are distributed tracing backends, but the ecosystem has been moving toward Jaeger (a CNCF graduated project) for its richer feature set, native Grafana integration, and alignment with the OpenTelemetry standard.

Comparison: Zipkin vs Jaeger

Feature
Zipkin
Jaeger

Origin

Twitter (2012)

Uber (2015)

CNCF Status

Not a CNCF project

✅ CNCF Graduated

UI

Simple, basic

Rich, feature-complete

Trace comparison

❌ Not supported

✅ Side-by-side comparison

Service dependency graph

Basic

✅ Rich, auto-generated

Search & filtering

Limited

✅ Advanced (tags, duration, errors)

Grafana integration

Plugin only

✅ Native datasource

OpenTelemetry (OTLP)

Not natively

✅ Native OTLP support

Spring Boot 3 client

micrometer-tracing-bridge-brave + zipkin-reporter-brave

micrometer-tracing-bridge-otel + opentelemetry-exporter-otlp

Storage backends

In-memory, MySQL, Cassandra, ES

Cassandra, ES, Kafka, Badger

Default UI port

9411

16686


How Jaeger Works

Jaeger follows the OpenTelemetry data model. Every request in the system produces a Trace, which is composed of Spans. Each span represents a unit of work done by one service.

How Jaeger Works — Distributed Tracing Concepts

Key Concepts

  • Trace — The full journey of a single request across all services. Identified by a unique traceId shared by every service that handles the request.

  • Span — A single unit of work within one service (e.g. an HTTP handler, a DB query). Has its own spanId, start time, and duration.

  • Parent-Child relationship — Spans form a tree. When order calls product via Feign, the product span is a child of the order span — this is what produces the indented waterfall view.

  • Tags & Logs — Key-value metadata attached to spans (HTTP status code, error messages, user IDs) that make debugging possible.

Architecture: How Traces Flow to Jaeger

Jaeger Architecture — Trace Flow from Spring Boot Services to Jaeger UI

Trace ID in Logs

With OTel, each log line includes the traceId and spanId automatically. In our project you will see:

  • d275c2bdbf332de2bbe5166ca341c58dtraceId (same across all services for one request)

  • b100f35cf830195aspanId (unique per service hop)

Copy the traceId and paste it into Jaeger's search bar to instantly find all spans for that request.


Migration from Zipkin to Jaeger

What Changed

The migration involved three layers: the Maven dependencies, the application configuration, and the infrastructure.

1. Maven Dependencies (per service)

2. Application Configuration

The config key moved from management.zipkin.tracing.endpoint (Brave/Zipkin protocol) to management.otlp.tracing.endpoint (OTLP protocol). The sampling and enabled flags remain unchanged:

3. Infrastructure — Docker Compose

4. Infrastructure — Kubernetes

The k8s/minikube/bootstrap/zipkin/ and k8s/aws-eks/bootstrap/zipkin/ directories were replaced with jaeger/ directories containing a deployment.yml and service.yml for the Jaeger all-in-one container.

Zero Java code changes were needed.


Implementation in Our Project

Jaeger Ports Reference

Port
Protocol
Purpose

16686

HTTP

Jaeger UI — open in browser

4318

HTTP

OTLP HTTP — services send traces here

4317

gRPC

OTLP gRPC — alternative transport

Accessing the Jaeger UI

Jaeger UI — Key Features

Search Traces

Select a Service, an optional Operation, set a time range, and click Find Traces. Each result shows a horizontal bar representing the total duration, and the number of spans inside.

Trace Detail View

Clicking a trace opens the waterfall view — each row is one span, color-coded per service, indented to show the parent-child tree. Clicking a span reveals its tags (HTTP method, status code, URL) and logs (error messages, events).

System Architecture Tab

Jaeger auto-generates a service dependency graph from the trace data. Every Feign call, RabbitMQ publish, or DB query is mapped. No manual configuration is needed.

Compare Traces

Select two traces side-by-side to compare their execution trees. Useful for spotting why the same operation is slow on one request but not another.

Last updated