Spring Boot Observability in 2026: OpenTelemetry, Distributed Tracing en Sollicitatievragen
Beheers Spring Boot observability met OpenTelemetry en Micrometer Tracing. Configureer OTLP-export, gebruik de Observation API en bereid je voor op technische sollicitatiegesprekken.

Spring Boot observability combineert logging, metrics en distributed tracing in een uniform systeem dat onthult hoe requests door microservices stromen. Vanaf Spring Boot 3 heeft het framework Micrometer Tracing geadopteerd (ter vervanging van Spring Cloud Sleuth) en de Observation API geintroduceerd, die een enkel instrumentatiepunt biedt dat zowel metrics als traces produceert.
Spring Boot raadt aan om Observation.observe() te gebruiken in plaats van OpenTelemetry direct aan te roepen. Een enkele instrumentatie-aanroep produceert metrics via Micrometer en traces via de OpenTelemetry bridge, waardoor code-duplicatie vermindert en consistente tag-naamgeving over alle signalen wordt gegarandeerd.
Hoe de Observation API Micrometer en OpenTelemetry Verbindt
De Observation API fungeert als een facade over zowel metrics als tracing. Wanneer code Observation.createNotStarted() aanroept, routeert Spring Boot de observation naar geregistreerde handlers: MeterObservationHandler voor Micrometer metrics en TracingObservationHandler voor distributed traces. Deze architectuur betekent: eenmaal instrumenteren, overal exporteren.
De bridge-dependency micrometer-tracing-bridge-otel verbindt Micrometer Tracing met de SDK van OpenTelemetry. Traces stromen door de SdkTracerProvider van OpenTelemetry en exporteren via OTLP naar backends zoals Jaeger, Tempo of elke OpenTelemetry-compatibele collector.
@Configuration
public class ObservabilityConfig {
@Bean
public ObservationRegistryCustomizer<ObservationRegistry> addLowCardinalityTags() {
return registry -> registry.observationConfig()
.observationHandler(new ObservationTextPublisher()); // Logs observations to console
}
}De bovenstaande configuratie registreert een ObservationHandler die elke observation logt. In productie sturen de automatisch geconfigureerde handlers data naar Micrometer registries en OpenTelemetry exporters zonder extra code.
Vereiste Dependencies voor Spring Boot 3.4 Tracing
Spring Boot 3.4 vereist expliciete dependencies voor distributed tracing. De spring-boot-starter-actuator levert de Observation API, maar tracing heeft de OpenTelemetry bridge en een exporter nodig.
<!-- pom.xml -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
</dependencies>Het micrometer-tracing-bridge-otel artifact verbindt Micrometer Tracing met de API van OpenTelemetry. De opentelemetry-exporter-otlp stuurt spans naar collectors via het OTLP-protocol over HTTP of gRPC. Spring Boot beheert versie-uitlijning via dependency management.
OTLP Export naar Jaeger of Tempo Configureren
Spring Boot configureert automatisch een OtlpHttpSpanExporter wanneer de OTLP-dependency aanwezig is. De exporter stuurt traces naar het endpoint gespecificeerd in application.yml.
# application.yml
management:
tracing:
sampling:
probability: 1.0 # 100% sampling for dev, reduce in production
otlp:
tracing:
endpoint: http://localhost:4318/v1/traces
opentelemetry:
resource-attributes:
service.name: order-service
deployment.environment: stagingDe resource-attributes koppelen metadata aan elke span. Backends zoals Grafana Tempo en Jaeger gebruiken deze attributen om traces te groeperen op service en omgeving. Het instellen van sampling.probability op 1.0 vangt alle requests tijdens ontwikkeling, maar productiesystemen samplen typisch tussen 1% en 10% om opslagkosten te beheersen.
Custom Observations Maken met Low en High Cardinality Tags
Observations ondersteunen twee tag-types: low cardinality voor metrics (begrensde waarden zoals HTTP-methodes of statuscodes) en high cardinality voor traces (onbegrensde waarden zoals gebruikers-IDs of request-IDs).
@Service
public class PaymentService {
private final ObservationRegistry observationRegistry;
public PaymentService(ObservationRegistry observationRegistry) {
this.observationRegistry = observationRegistry;
}
public PaymentResult processPayment(PaymentRequest request) {
return Observation.createNotStarted("payment.process", observationRegistry)
.lowCardinalityKeyValue("payment.method", request.getMethod().name()) // enum: CARD, BANK_TRANSFER
.lowCardinalityKeyValue("currency", request.getCurrency()) // bounded: USD, EUR, GBP
.highCardinalityKeyValue("payment.id", request.getPaymentId()) // unique per request
.highCardinalityKeyValue("customer.id", request.getCustomerId()) // high cardinality
.observe(() -> executePayment(request));
}
private PaymentResult executePayment(PaymentRequest request) {
// Payment gateway call
return new PaymentResult(true, "TXN-" + UUID.randomUUID());
}
}Low cardinality tags verschijnen in zowel metrics als traces. High cardinality tags verschijnen alleen in traces omdat metrics met onbegrensde dimensies de opslag laten exploderen. Dit onderscheid voorkomt Prometheus cardinaliteitsbommen terwijl trace-details rijk blijven.
Interviewers vragen vaak waarom bepaalde tags van metrics moeten worden uitgesloten. Het antwoord betreft cardinaliteit: een gebruikers-ID tag op een metric creëert één time series per gebruiker, potentieel miljoenen series. Monitoring backends worstelen met hoge cardinaliteit, wat leidt tot geheugenuitputting en trage queries. Traces verwerken hoge cardinaliteit via sampling, waardoor ze de juiste plek zijn voor request-specifieke identifiers.
Klaar om je Spring Boot gesprekken te halen?
Oefen met onze interactieve simulatoren, flashcards en technische tests.
Trace Context Propageren Over Asynchrone Grenzen
Distributed tracing vereist context propagatie. HTTP headers dragen trace IDs tussen services, maar asynchrone operaties zoals @Async methodes of CompletableFuture chains kunnen context verliezen als ze niet geconfigureerd zijn.
Spring Boot 3.4 biedt automatische propagatie voor reactive streams en @Async methodes wanneer geconfigureerd:
# application.yml
spring:
reactor:
context-propagation: auto
task:
execution:
propagate-context: trueVoor custom TaskExecutor beans worden deze gewrapt met ContextPropagatingTaskDecorator:
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(50);
executor.setTaskDecorator(new ContextPropagatingTaskDecorator());
executor.initialize();
return executor;
}
}De decorator kopieert de huidige Observation en trace context naar de asynchrone thread. Zonder deze decorator hebben spans die in asynchrone tasks worden gestart geen parent, wat de trace tree verbreekt.
@Observed en @NewSpan Annotaties Gebruiken
Spring Boot 3.4 ondersteunt declaratieve observability via annotaties. Annotatieverwerking wordt ingeschakeld door de AspectJ weaver toe te voegen:
<!-- pom.xml -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency># application.yml
management:
observations:
annotations:
enabled: true@Service
public class InventoryService {
@Observed(name = "inventory.check", contextualName = "checkStock")
public StockLevel checkStock(String productId) {
// Database query
return new StockLevel(productId, 42);
}
@NewSpan("inventory.reserve") // Creates a child span under the current trace
public ReservationResult reserveStock(String productId, int quantity) {
// Update inventory
return new ReservationResult(true, "RES-" + System.currentTimeMillis());
}
}@Observed creëert zowel een metric (timer) als een span. @NewSpan creëert alleen een span, nuttig wanneer de operatie al ergens anders metrics heeft. Beide annotaties verwerken automatisch exception recording en span status.
Auto-geïnstrumenteerde Componenten in Spring Boot 3.4
Spring Boot 3.4 auto-instrumenteert verschillende componenten zonder codewijzigingen:
| Component | Observation Naam | Wat het Vangt |
|---|---|---|
| Spring MVC | http.server.requests | Request pad, methode, status, exception |
| WebClient | http.client.requests | Uitgaande HTTP calls |
| RestClient | http.client.requests | Uitgaande HTTP calls (Spring 6.1+) |
| Spring Kafka | spring.kafka.listener | Consumer group, topic, partition |
| Spring Data JPA | spring.data.repository | Repository methode, query tijd |
| Scheduled Tasks | spring.scheduling | Task naam, uitvoeringstijd |
De Spring Boot Actuator documentatie vermeldt alle auto-geïnstrumenteerde componenten. Third-party libraries zoals Datasource Micrometer voegen JDBC query tracing toe.
Observations Filteren om Ruis te Verminderen
Health checks, readiness probes en statische resources genereren ruis in traces. Deze worden uitgefilterd met predicates:
@Configuration
public class ObservationFilterConfig {
@Bean
public ObservationPredicate noHealthChecks() {
return (name, context) -> !name.equals("http.server.requests")
|| !isHealthEndpoint(context);
}
private boolean isHealthEndpoint(Observation.Context context) {
if (context instanceof ServerRequestObservationContext http) {
String path = http.getCarrier().getRequestURI();
return path.startsWith("/actuator/health") || path.startsWith("/actuator/ready");
}
return false;
}
}Alternatief kunnen observations op naam worden uitgeschakeld in de configuratie:
# application.yml
management:
observations:
enable:
spring.security: false # Disable Spring Security observations
http.server.requests.actuator: false # Custom predicate nameSampling reduceert het percentage verzamelde traces over alle endpoints. Filtering verwijdert specifieke endpoints volledig. Filtering wordt gebruikt voor endpoints die nooit diagnostische waarde bieden (health checks, metrics scraping). Sampling wordt gebruikt om kosten te beheersen terwijl representatieve data behouden blijft.
Logs Correleren met Trace IDs
Spring Boot 3.4 voegt automatisch trace en span IDs toe aan de MDC (Mapped Diagnostic Context) wanneer Micrometer Tracing actief is. Logback en Log4j2 kunnen deze IDs opnemen in de log output:
<!-- logback-spring.xml -->
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - traceId=%X{traceId} spanId=%X{spanId} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
</configuration>Met dit pattern bevat elke logregel de trace ID. Zoeken in logs op trace ID retourneert alle berichten van een enkele request over alle services, waardoor logs worden gecorreleerd met spans in Jaeger of Tempo.
Veelvoorkomende Sollicitatievragen over Spring Boot Observability
Interviewers beoordelen zowel conceptueel begrip als praktische ervaring met observability. Deze vragen komen frequent voor in senior backend rollen.
V: Wat is het verschil tussen Micrometer Tracing en OpenTelemetry?
Micrometer Tracing is een vendor-neutrale API voor distributed tracing, vergelijkbaar met hoe Micrometer metrics abstraheert. OpenTelemetry is een specifieke implementatie en protocol. Spring Boot gebruikt Micrometer Tracing als API en bridget naar OpenTelemetry voor export via micrometer-tracing-bridge-otel. Deze gelaagdheid laat applicaties van backend wisselen zonder codewijzigingen.
V: Waarom raadt Spring de Observation API aan boven directe OpenTelemetry instrumentatie?
De Observation API biedt een enkel instrumentatiepunt dat zowel metrics als traces produceert. Directe OpenTelemetry calls produceren alleen traces. Het gebruik van Observation.observe() genereert een timer metric en een span vanuit dezelfde code, wat duplicatie vermindert en consistente naamgeving garandeert.
V: Hoe debug je een trace die een gap tussen spans toont?
Gaps duiden op ontbrekende instrumentatie of verbroken context propagatie. Controleer of de code asynchrone operaties gebruikt zonder ContextPropagatingTaskDecorator. Verifieer dat HTTP clients geïnstrumenteerd zijn (WebClient, RestClient, of een handmatig gewrapte RestTemplate). Voor message queues, bevestig dat trace headers propageren via message properties.
V: Wat gebeurt er als je een high cardinality tag aan een metric toevoegt?
Elke unieke tag waarde creëert een nieuwe time series. Een gebruikers-ID tag met miljoenen gebruikers creëert miljoenen series, wat geheugen uitput in Prometheus of andere TSDB backends. De oplossing is het gebruik van highCardinalityKeyValue() in plaats van lowCardinalityKeyValue(), wat de tag alleen aan traces toevoegt waar hoge cardinaliteit verwacht wordt.
Een Distributed Tracing Pipeline Bouwen met Docker Compose
Een lokale observability stack helpt bij het valideren van instrumentatie voor deployment naar productie. Dit voorbeeld gebruikt de OpenTelemetry Collector en Jaeger:
# docker-compose.yml
services:
otel-collector:
image: otel/opentelemetry-collector-contrib:0.102.0
command: ["--config", "/etc/otel-collector-config.yml"]
volumes:
- ./otel-collector-config.yml:/etc/otel-collector-config.yml
ports:
- "4318:4318" # OTLP HTTP
- "4317:4317" # OTLP gRPC
jaeger:
image: jaegertracing/jaeger:2.3
ports:
- "16686:16686" # UI
environment:
- COLLECTOR_OTLP_ENABLED=true
app:
build: .
environment:
- MANAGEMENT_OTLP_TRACING_ENDPOINT=http://otel-collector:4318/v1/traces
depends_on:
- otel-collector# otel-collector-config.yml
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
grpc:
endpoint: 0.0.0.0:4317
processors:
batch:
timeout: 1s
send_batch_size: 1024
exporters:
otlp/jaeger:
endpoint: jaeger:4317
tls:
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp/jaeger]De collector ontvangt spans van de Spring Boot applicatie en stuurt ze door naar Jaeger. Deze architectuur maakt het mogelijk om exporters toe te voegen (Tempo, Zipkin, cloud backends) zonder applicatiecode te wijzigen.
Begin met oefenen!
Test je kennis met onze gespreksimulatoren en technische tests.
Belangrijke Inzichten voor Spring Boot Observability
- De Observation API unificeert metrics en tracing: één
Observation.observe()call produceert zowel een timer metric als een span, waardoor dubbele instrumentatie wordt geëlimineerd. - Voeg
micrometer-tracing-bridge-otelenopentelemetry-exporter-otlptoe om OTLP export in te schakelen. Spring Boot 3.4 configureert automatisch de HTTP exporter met het endpoint uitmanagement.otlp.tracing.endpoint. - Gebruik
lowCardinalityKeyValue()voor dimensies die in metrics verschijnen (begrensde waarden). GebruikhighCardinalityKeyValue()voor trace-only data (gebruikers-IDs, request-IDs). - Schakel context propagatie in voor asynchrone code met
spring.task.execution.propagate-context=trueen wrap custom executors metContextPropagatingTaskDecorator. - Filter luidruchtige endpoints zoals
/actuator/healthmetObservationPredicatebeans om traces gefocust te houden op business operaties. - Log patterns moeten
%X{traceId}bevatten om logregels te correleren met distributed traces in je observability backend. - Sollicitatievragen over observability focussen op cardinaliteit, context propagatie failures, en het onderscheid tussen de Observation API en direct OpenTelemetry gebruik.
Zie jij de bug in Spring Boot?
Een echt codefragment, een verborgen bug, één poging per dag. Zonder account uit te proberen.

Geschreven door
Anthony Fillion-MailletOprichter van SharpSkill
Al meer dan 10 jaar fullstack-ontwikkelaar. Hij leidt SharpSkill en staat in voor alles wat hier verschijnt.
Bijgewerkt op 19 september 2026
Delen
Gerelateerde artikelen

Spring Boot YAML vs Properties: Configuratievergelijking en Sollicitatievragen 2026
Uitgebreide vergelijking tussen YAML en Properties-bestanden in Spring Boot. Leer over syntax, best practices en veelgestelde sollicitatievragen over geëxternaliseerde configuratie.

Gestructureerde logging in Spring Boot 2026: JSON-logs voor productie met Logback en OpenTelemetry
Volledige gids voor gestructureerde logging in Spring Boot 4.x. Native JSON-ondersteuning, OpenTelemetry starter, MDC tracing en ELK Stack integratie voor productie observability.

Spring Kafka: event-driven architectuur met resiliënte consumers
Volledige Spring Kafka-gids voor event-driven architecturen. Configuratie, resiliënte consumers, retry-strategieën, dead letter queues en productiepatronen voor gedistribueerde applicaties.