Advanced Observability with OpenTelemetry in Spring Boot Applications
Shant Khayalian
Co-Founder & Managing Director @Balian's Technologies | Custom App Development & IT Consulting | Specializing in Agriculture, Humanitarian, Environmental Innovations.
Observability is a critical aspect of modern application development, enabling developers to monitor, debug, and optimize distributed systems. OpenTelemetry is an open-source observability framework that provides unified support for tracing, metrics, and logging. In this guide, we’ll cover setting up OpenTelemetry in a Spring Boot application, integrating it with tools like Grafana and Jaeger, and optimizing observability configurations.
1. Introduction to OpenTelemetry
OpenTelemetry offers a vendor-neutral framework to instrument applications and collect observability data. It supports:
By using OpenTelemetry, you can gain insights into application behavior, pinpoint bottlenecks, and ensure system reliability.
2. Setting Up OpenTelemetry in Spring Boot
2.1 Add OpenTelemetry Dependencies
Include the following dependencies in your pom.xml:
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-spring-boot-starter</artifactId>
<version>1.25.0</version>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
<version>1.25.0</version>
</dependency>
2.2 Configure OpenTelemetry Exporters
Exporters send collected observability data to external monitoring tools. For example, the OTLP Exporter sends data to tools like Grafana Tempo and Jaeger.
Add the following configuration to application.yml:
otel:
tracing:
enabled: true
exporter:
otlp:
endpoint: https://localhost:4317 # OTLP endpoint for collectors
2.3 Enable Auto-Instrumentation
OpenTelemetry provides automatic instrumentation for common libraries such as Spring MVC, Spring Data, and Hibernate. Include the OpenTelemetry agent in your JVM startup options:
-javaagent:/path/to/opentelemetry-javaagent.jar
-Dotel.exporter.otlp.endpoint=https://localhost:4317
3. Distributed Tracing Across Microservices
Distributed tracing captures the lifecycle of a request as it propagates through multiple services in a microservices architecture. It helps identify latency bottlenecks and visualize dependencies between services.
3.1 Add Trace Propagation
To propagate trace context between services, ensure headers like traceparent and tracestate are included in requests.
@RestController
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/orders")
public String getOrders() {
return restTemplate.getForObject("https://inventory-service/items", String.class);
}
}
Spring Boot automatically propagates trace headers with RestTemplate and WebClient when OpenTelemetry is configured.
3.2 View Traces in Jaeger
Run a Jaeger instance to visualize traces:
docker run -d --name jaeger \
-e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \
-p 16686:16686 \
-p 14268:14268 \
jaegertracing/all-in-one:1.41
Visit https://localhost:16686 to view traces and analyze the lifecycle of requests.
4. Capturing Metrics
Metrics provide quantitative insights into system performance, such as throughput, latency, and error rates.
4.1 Configure Metrics Exporter
Enable the Prometheus Exporter to send metrics to Prometheus for visualization in Grafana.
Add the Prometheus exporter dependency:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-prometheus</artifactId>
<version>1.25.0</version>
</dependency>
Configure the metrics endpoint in application.yml:
management:
endpoints:
web:
exposure:
include: prometheus
metrics:
export:
prometheus:
enabled: true
Access metrics at https://localhost:8080/actuator/prometheus.
4.2 Monitor Metrics in Grafana
docker run -d --name prometheus -p 9090:9090 prom/prometheus
2. Configure a Grafana dashboard:
5. Optimizing Observability Configurations
Observability can introduce overhead if not properly managed. Here’s how to optimize configurations for performance:
5.1 Reduce Sampling Rates
Sampling reduces the volume of trace data by capturing only a subset of requests. Adjust sampling rates in application.yml:
otel:
tracing:
sampler:
probability: 0.1 # Sample 10% of traces
5.2 Use Batching for Exporters
Batching reduces the frequency of data exports, minimizing resource usage.
otel:
exporter:
batch:
max-batch-size: 512
max-queue-size: 2048
5.3 Focus on High-Value Traces and Metrics
Instrument only critical parts of your application, such as:
6. Fault Tolerance and Reliability
6.1 Handle Missing Trace Context
Ensure trace propagation doesn’t fail when context headers are missing:
@Bean
public RestTemplate restTemplate() {
return new RestTemplateBuilder().defaultHeader(HttpHeaders.TRACEPARENT, "").build();
}
6.2 Monitor Exporter Failures
Monitor and log errors in exporters to ensure observability data is reliably delivered.
otel:
exporter:
logging:
enabled: true
7. Best Practices for Observability with OpenTelemetry
OpenTelemetry in Spring Boot provides end-to-end observability, enabling you to monitor distributed systems, debug performance bottlenecks, and ensure reliability. By integrating tracing, metrics, and logs into a unified platform and leveraging tools like Jaeger and Grafana, you can gain valuable insights into your application’s behavior.
With optimized configurations and a focus on high-value observability, Spring Boot applications can achieve advanced monitoring without sacrificing performance, making them robust and easier to maintain in production environments.
Find us
linkedin Shant Khayalian Facebook Balian’s X-platform Balian’s web Balian’s Youtube Balian’s
#SpringBoot #OpenTelemetry #Observability #Tracing #Metrics #Logging #Grafana #Jaeger #Microservices