Skip to main content

Spring Boot

Implement OpenTelemetry instrumentation for Spring Boot applications to collect traces and metrics, and monitor HTTP requests using the Java OTel SDK.

Note: This guide provides a concise overview. For complete information, consult the official OpenTelemetry documentation.


Overview

This guide demonstrates how to:

  • Set up OpenTelemetry instrumentation for Spring Boot
  • Configure automatic request and response tracing
  • Implement custom instrumentation
  • Collect HTTP metrics
  • Export telemetry data to OpenTelemetry Collector

Prerequisites

  • Java 17 or later
  • Spring Boot 3.2.0 or later
  • Maven 3.6+ or Gradle 7.6+

Required Dependencies

Maven (pom.xml)

<properties>
<opentelemetry.version>1.32.0</opentelemetry.version>
<opentelemetry.instrumentation.version>2.1.0</opentelemetry.instrumentation.version>
<micrometer.version>1.12.0</micrometer.version>
</properties>

<dependencyManagement>
<dependencies>
<!-- OpenTelemetry Instrumentation BOM -->
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-instrumentation-bom</artifactId>
<version>
${opentelemetry.instrumentation.version}-alpha
</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<!-- Spring Boot Starters -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- OpenTelemetry -->
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-spring-boot-starter</artifactId>
</dependency>

<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-otlp</artifactId>
</dependency>
</dependencies>

Gradle (build.gradle)

plugins {
id 'java'
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
}

ext {
set('opentelemetry.version', '1.32.0')
set('opentelemetry.instrumentation.version', '2.1.0')
set('micrometer.version', '1.12.0')
}

dependencyManagement {
imports {
// OpenTelemetry Instrumentation BOM
mavenBom "io.opentelemetry.instrumentation:" +
"opentelemetry-instrumentation-bom:" +
"${opentelemetry.instrumentation.version}-alpha"
}
}

dependencies {
// Spring Boot Starters
implementation 'org.springframework.boot:spring-boot-starter-web'

// OpenTelemetry
implementation 'io.opentelemetry.instrumentation:' +
'opentelemetry-spring-boot-starter'
implementation 'io.micrometer:micrometer-registry-otlp'
}

Configuration (application.properties)

# Server
server.port=8080
server.address=0.0.0.0

# OpenTelemetry
otel.service.name=your-service-name
otel.resource.attributes=service.namespace=your-namespace,\
deployment.environment=dev

# OTLP Exporter
otel.traces.exporter=otlp
otel.metrics.exporter=otlp
otel.logs.exporter=otlp
otel.exporter.otlp.endpoint=http://localhost:4318
otel.exporter.otlp.protocol=http/protobuf

# Actuator
management.endpoints.web.exposure.include=health,info,metrics,prometheus
management.tracing.sampling.probability=1.0

Traces

Auto Instrumentation

Spring Boot auto-configures instrumentation for:

  • HTTP requests/responses
  • JDBC operations
  • WebClient / RestTemplate
  • Kafka / Redis / MongoDB

Custom Instrumentation

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
import org.springframework.stereotype.Service;

@Service
public class MyService {
private final Tracer tracer;

public MyService(OpenTelemetry openTelemetry) {
this.tracer = openTelemetry.getTracer(MyService.class.getName());
}

public void doWork() {
Span span = tracer.spanBuilder("my-operation").startSpan();
try (Scope scope = span.makeCurrent()) {
span.setAttribute("custom.attribute", "value");
// business logic
} finally {
span.end();
}
}
}

Metrics

Auto Instrumentation

With Micrometer and Spring Boot Actuator, you get:

  • JVM metrics (memory, threads, GC)
  • HTTP server metrics
  • DB connection pool metrics
  • System-level metrics

Custom Metrics

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Component;

@Component
public class MyMetrics {
private final Counter myCounter;

public MyMetrics(MeterRegistry registry) {
this.myCounter = Counter.builder("my.custom.counter")
.description("Counts custom operations")
.tag("environment", "dev")
.register(registry);
}

public void incrementCounter() {
myCounter.increment();
}
}

Running with Docker Compose

services:
otel-collector:
image: otel/opentelemetry-collector-contrib:0.128.0
ports:
- "4317:4317" # OTLP gRPC
- "4318:4318" # OTLP HTTP
volumes:
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml
command: ["--config=/etc/otel-collector-config.yaml"]

your-spring-app:
build: .
environment:
- OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
ports:
- "8080:8080"
depends_on:
- otel-collector

Viewing Telemetry

Logs, traces and metrics are exported to the base14 Scout observability backend refer .

References