In modern microservices architectures, tracking requests as they flow across service boundaries is critical for debugging performance bottlenecks, diagnosing failures, and maintaining system reliability. While Zipkin and Jaeger have been popular distributed tracing tools, OpenTelemetry has emerged as the new standard, offering vendor-neutral instrumentation, logs, metrics, and traces in a unified framework.
This article explores:
- Why OpenTelemetry (OTel) is replacing traditional tracing tools
- How to integrate OpenTelemetry with Spring Boot
- Best practices for distributed tracing in microservices
- Visualizing traces with Jaeger, Zipkin, and Grafana
1. Why OpenTelemetry? The Evolution Beyond Zipkin
The Limitations of Traditional Tracing (Zipkin/Jaeger)
- Vendor lock-in: Zipkin/Jaeger require specific SDKs.
- Limited correlation: Metrics, logs, and traces were separate.
- Manual instrumentation: Required explicit code changes.
How OpenTelemetry Solves These Problems
- Standardized APIs: Works across multiple backends (Jaeger, Zipkin, Prometheus, etc.).
- Auto-instrumentation: Captures traces without code changes.
- Unified Observability: Combines traces, metrics, and logs.
2. Setting Up OpenTelemetry in Spring Boot
Step 1: Add Dependencies
<!-- OpenTelemetry SDK & Auto-Instrumentation --> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-api</artifactId> <version>1.30.0</version> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-sdk</artifactId> <version>1.30.0</version> </dependency> <dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency>
Step 2: Configure application.yml
opentelemetry: service: name: order-service traces: exporter: otlp: endpoint: http://otel-collector:4317 # OTLP Collector logs: exporter: otlp: enabled: true metrics: exporter: otlp: enabled: true
Step 3: Deploy an OpenTelemetry Collector
# docker-compose.yml services: otel-collector: image: otel/opentelemetry-collector ports: - "4317:4317" # OTLP gRPC - "4318:4318" # OTLP HTTP volumes: - ./otel-config.yaml:/etc/otel-config.yaml command: ["--config=/etc/otel-config.yaml"]
Step 4: Export Traces to Jaeger/Zipkin
# otel-config.yaml exporters: jaeger: endpoint: "jaeger:14250" tls: insecure: true zipkin: endpoint: "http://zipkin:9411/api/v2/spans" service: pipelines: traces: receivers: [otlp] processors: [batch] exporters: [jaeger, zipkin]
3. Advanced Distributed Tracing Techniques
Custom Spans for Business Logic
@GetMapping("/process")
public String processOrder() {
Span span = Span.current();
span.setAttribute("order.id", "12345"); // Custom attributes
try (Scope scope = span.makeCurrent()) {
// Business logic
inventoryService.reserveItems();
paymentService.chargeCustomer();
return "Order processed!";
} catch (Exception e) {
span.recordException(e); // Error tracking
throw e;
}
}
Baggage Propagation (Cross-Service Context)
// Set baggage in Service A
Baggage.current()
.toBuilder()
.put("user.id", "user-123")
.build()
.makeCurrent();
// Retrieve in Service B
String userId = Baggage.current().getEntryValue("user.id");
Sampling Strategies
# application.yml opentelemetry: traces: sampler: parentbased_always_on # or "dynamic" for adaptive sampling
4. Visualizing Traces: Jaeger vs. Zipkin vs. Grafana
| Tool | Strengths | Best For |
|---|---|---|
| Jaeger | Powerful querying, dependency graphs | Debugging complex microservices |
| Zipkin | Simple UI, lightweight | Basic tracing needs |
| Grafana Tempo | Deep integration with Prometheus metrics | Full observability (logs + metrics + traces) |
5. Best Practices for Production
- Use OTLP (OpenTelemetry Protocol) instead of vendor-specific exporters.
- Enable Auto-Instrumentation for Spring Web, JDBC, Kafka, etc.
- Implement Sampling to reduce storage costs.
- Correlate Logs & Traces using
trace_id. - Monitor Collector Performance to avoid bottlenecks.
Conclusion
OpenTelemetry provides a future-proof, vendor-neutral way to implement distributed tracing in Spring Boot microservices. By replacing Zipkin/Jaeger with OTel, teams gain:
- Auto-instrumentation (no manual code changes)
- Unified observability (traces + metrics + logs)
- Better debugging with correlated telemetry
Further Reading
Thank you!
We will contact you soon.
Eleftheria DrosopoulouApril 11th, 2025Last Updated: April 12th, 2025

This site uses Akismet to reduce spam. Learn how your comment data is processed.