Integrate OpenTelemetry with Spring Boot in 5 Minutes for Microservice Monitoring and Tracing

This guide shows how to quickly add OpenTelemetry to a Spring Boot microservice, covering Docker‑based Jaeger setup, Maven dependencies, YAML configuration, automatic instrumentation, custom spans, production tuning, e‑commerce tracing examples, and common pitfalls to avoid.

Java Companion
Java Companion
Java Companion
Integrate OpenTelemetry with Spring Boot in 5 Minutes for Microservice Monitoring and Tracing

Why OpenTelemetry?

In a microservice architecture, diagnosing cross‑service failures—such as a payment error or slow response—can be extremely hard. OpenTelemetry (OTel), a CNCF project, unifies tracing, metrics, and logs, and a 2024 DevOps report says it can cut fault‑location time by 67%.

1. Quick Local Setup

Start Jaeger

Run the all‑in‑one Jaeger container with a single Docker command:

docker run -d -p 16686:16686 -p 4317:4317 \
  -e COLLECTOR_OTLP_ENABLED=true \
  jaegertracing/all-in-one

Access the UI at http://localhost:16686 to view traces.

2. Add Spring Boot Dependency

Include the OpenTelemetry starter in pom.xml (or Gradle):

<dependency>
  <groupId>io.opentelemetry.instrumentation</groupId>
  <artifactId>opentelemetry-spring-boot-starter</artifactId>
  <version>2.2.0</version>
</dependency>

3. Configure application.yml

opentelemetry:
  service.name: payment-service
  traces.exporter: otlp
  metrics.exporter: none
  logs.exporter: none
  protocol: grpc
  endpoint: http://localhost:4317

2. Automatic Instrumentation

OTel automatically captures key operations without code changes:

HTTP requests (method, path, status)

JDBC queries (parameterized SQL, no sensitive data)

Kafka/RabbitMQ message send/receive

For example, a simple controller needs no extra annotations:

@RestController
@RequestMapping("/orders")
public class OrderController {
    @Autowired
    private OrderService orderService;

    // Span name generated automatically: GET /orders/{id}
    @GetMapping("/{id}")
    public Order getOrder(@PathVariable Long id) {
        return orderService.findById(id);
    }
}

3. Custom Spans for Business Details

When deeper insight is required (e.g., payment amount, risk‑check results), create spans manually:

@Service
public class PaymentService {
    public Payment processPayment(PaymentRequest request) {
        Span span = Span.current()
            .setAttribute("payment.amount", request.getAmount())
            .setAttribute("payment.currency", "CNY");
        span.addEvent("risk_check_start");
        riskService.check(request);
        span.addEvent("risk_check_complete");
        try (Scope scope = span.makeCurrent()) {
            return paymentGateway.charge(request);
        } catch (Exception e) {
            span.recordException(e);
            span.setStatus(StatusCode.ERROR);
            throw e;
        }
    }
}

4. Production‑Ready Configuration

After development validation, tune the following settings to balance performance and observability:

sampling.probability : 0.1‑0.2 (recommended for 10k QPS to avoid full‑sample overload)

batch.export.delay : 500 ms (trade‑off between latency and throughput)

max.export.batch : 512 (prevent memory spikes)

5. E‑Commerce Use‑Case

Trace Visualization

A typical payment flow—order → payment → risk check → bank gateway—appears as a single trace in Jaeger, allowing you to spot slow stages such as a 200 ms risk‑check latency.

Metrics with Grafana & Prometheus

# Payment success rate (1‑minute window)
sum(rate(payment_completed_total[1m])) by (method) /
    sum(rate(payment_started_total[1m]))

Creating a Grafana panel for this query provides real‑time success‑rate monitoring and early alerts.

6. Pitfalls to Avoid

Thread‑Pool Context Loss

When using a thread pool, traces can break. Add an OTel context decorator:

@Configuration
public class ThreadPoolConfig {
    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setTaskDecorator(new OtelContextDecorator());
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        return executor;
    }
}

Span Naming Rules

Wrong: /orders/123 (dynamic, prevents aggregation)

Correct: /orders/{id} (template‑based, aggregates automatically)

7. Recommended Toolchain

Development: Jaeger All‑in‑One (lightweight, zero‑config)

Production: SigNoz + Prometheus (scalable storage and advanced analysis)

8. Official Resources

OpenTelemetry Java docs: https://opentelemetry.io/docs/instrumentation/java/

Spring Boot integration examples: https://github.com/open-telemetry/opentelemetry-java-instrumentation

Conclusion

Integrating OpenTelemetry with Spring Boot provides a simple, efficient way to achieve full‑stack tracing and monitoring for microservices, turning vague fault‑location into precise, actionable insight.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

microservicesobservabilityOpenTelemetryPrometheusSpring BootTracingGrafanajaeger
Java Companion
Written by

Java Companion

A highly professional Java public account

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.