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.

Traditionele tekstlogs worden in productie snel onbeheersbaar. Met honderden instanties die duizenden regels per seconde produceren, wordt zoeken naar een specifieke fout een nachtmerrie. Gestructureerde JSON-logs veranderen die situatie volledig: elk event wordt doorzoekbaar en automatisch analyseerbaar.
Spring Boot 4.x (gebouwd op Spring Framework 7) ondersteunt gestructureerde JSON-logging native met ECS-, Logstash- en GELF-formaten. De nieuwe spring-boot-starter-opentelemetry biedt unified observability zonder externe afhankelijkheden.
Waarom gestructureerde logging in Spring Boot
Beperkingen van klassieke tekstlogs
Een typische tekstlog ziet er zo uit:
2026-08-22 10:15:32.456 INFO [order-service,abc123] c.e.s.OrderService - Order created for user john@example.com, amount: 150.00€, items: 3Dit formaat brengt in productie meerdere problemen mee. Specifieke informatie eruit halen vereist complexe en breekbare reguliere expressies. Correlatie tussen services vraagt strikte conventies die elk team anders interpreteert. Analysetools zoals Elasticsearch hebben moeite om deze ongestructureerde strings efficiënt te indexeren.
Voordelen van het JSON-formaat
Hetzelfde event in JSON wordt onmiddellijk bruikbaar:
{
"@timestamp": "2026-08-22T10:15:32.456Z",
"level": "INFO",
"logger": "com.example.service.OrderService",
"message": "Order created",
"service": "order-service",
"traceId": "abc123",
"userId": "john@example.com",
"orderId": "ORD-789456",
"amount": 150.00,
"currency": "EUR",
"itemCount": 3
}Elk veld wordt filterbaar en aggregeerbaar. Een Elasticsearch-query vindt onmiddellijk alle bestellingen boven 100 € van de laatste vijftien minuten. Kibana-dashboards visualiseren trends zonder handmatige parsing. Dit is bijzonder relevant bij Spring Boot interviewvragen, waar begrip van observability-patronen in productie senior kandidaten onderscheidt.
Native configuratie voor gestructureerde logging in Spring Boot 4.x
Gestructureerde JSON-logs activeren
Spring Boot 4.x, gebouwd op Spring Framework 7, introduceert volwassen ondersteuning voor gestructureerde logging via de eigenschap logging.structured. Deze aanpak vereist geen extra afhankelijkheid en integreert rechtstreeks met Logback 1.5.38.
# application.yml
# Native structured logging configuration for Spring Boot 4.x
logging:
structured:
# Output format: ecs (Elastic), logstash, gelf
format:
console: ecs
file: ecs
file:
name: /var/log/app/application.log
level:
root: INFO
com.example: DEBUGHet ECS-formaat (Elastic Common Schema) garandeert directe compatibiliteit met Elasticsearch en Kibana zonder bijkomende configuratie.
JSON-velden aanpassen
Om aan elke log businessvelden toe te voegen, laat Spring Boot toe extra attributen te configureren.
# application.yml
# Custom fields in structured logs
logging:
structured:
format:
console: ecs
ecs:
# Service information added to every log
service:
name: ${spring.application.name}
version: ${app.version:1.0.0}
environment: ${spring.profiles.active:default}
node-name: ${HOSTNAME:unknown}// Programmatic configuration for additional fields
package com.example.logging.config;
import org.springframework.boot.logging.structured.StructuredLogFormatterCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class LoggingConfig {
@Bean
StructuredLogFormatterCustomizer<EcsStructuredLogFormatter> ecsCustomizer() {
return formatter -> formatter
// Adds static fields to all logs
.addStaticField("team", "backend")
.addStaticField("region", System.getenv("AWS_REGION"))
// Customizes exception formatting
.setIncludeStacktrace(true)
.setStacktraceMaxLength(5000);
}
}Deze velden verschijnen in elke logregel en vergemakkelijken filtering per team of regio in dashboards.
OpenTelemetry Starter voor complete observability
De nieuwe standaard in Spring Boot 4
Spring Boot 4.0 introduceert spring-boot-starter-opentelemetry, ter vervanging van de complexe multi-dependency setup van eerdere versies. Deze enkele afhankelijkheid biedt vendor-neutrale observability inclusief traces, metrics en log correlatie.
<!-- pom.xml -->
<!-- OpenTelemetry starter for Spring Boot 4.x -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-opentelemetry</artifactId>
</dependency>
<!-- Log correlation for Logback -->
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-logback-appender-1.0</artifactId>
<version>2.21.0-alpha</version>
</dependency>Deze starter bevat de OpenTelemetry API, de Micrometer tracing bridge en OTLP exporters. Spring Cloud Sleuth wordt nu als legacy beschouwd, met OpenTelemetry als de industriestandaard voor distributed tracing.
OpenTelemetry configureren met gestructureerde logs
# application.yml
# OpenTelemetry configuration with structured logging
spring:
application:
name: order-service
group: commerce
otel:
exporter:
otlp:
endpoint: http://otel-collector:4317
protocol: grpc
resource:
attributes:
service.namespace: production
deployment.environment: prod
logging:
structured:
format:
console: ecs
pattern:
level: "%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]"Trace- en span-ID's worden automatisch in de MDC geïnjecteerd, waardoor logs gecorreleerd worden met distributed traces over services heen. Voor meer informatie over productie-monitoring, zie de Spring Boot Actuator gids met Micrometer en Prometheus.
ZipkinWithOpenTelemetryTracingAutoConfiguration is deprecated en wordt verwijderd in Spring Boot 4.2. Migreer naar native OTLP exporters voor toekomstige compatibiliteit.
Klassieke Logback-configuratie met JSON-encoder
Logstash Encoder voor geavanceerde aanpassing
Voor geavanceerde aanpassingsbehoeften of bij migratie van oudere Spring Boot versies blijft Logstash Logback Encoder 9.0 beschikbaar. Versie 9.0 vereist Jackson 3.0 en minimaal Java 17.
<!-- pom.xml -->
<!-- Dependency for JSON logging with Logback (Jackson 3 required) -->
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>9.0</version>
</dependency>Volledige Logback-configuratie
Het bestand logback-spring.xml biedt volledige controle over het uitvoerformaat.
<!-- src/main/resources/logback-spring.xml -->
<!-- Logback configuration for structured JSON logs -->
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- Spring Boot properties -->
<springProperty scope="context" name="appName" source="spring.application.name" defaultValue="app"/>
<springProperty scope="context" name="appVersion" source="app.version" defaultValue="1.0.0"/>
<!-- JSON console appender for production -->
<appender name="JSON_CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<!-- Custom fields added to every log -->
<customFields>{"service":"${appName}","version":"${appVersion}"}</customFields>
<!-- Includes MDC (tracing context) -->
<includeMdcKeyName>traceId</includeMdcKeyName>
<includeMdcKeyName>spanId</includeMdcKeyName>
<includeMdcKeyName>userId</includeMdcKeyName>
<includeMdcKeyName>requestId</includeMdcKeyName>
<!-- ISO8601 timestamp format -->
<timestampPattern>yyyy-MM-dd'T'HH:mm:ss.SSSZ</timestampPattern>
<!-- Complete stack traces -->
<throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
<maxDepthPerThrowable>30</maxDepthPerThrowable>
<maxLength>4096</maxLength>
<shortenedClassNameLength>36</shortenedClassNameLength>
<rootCauseFirst>true</rootCauseFirst>
</throwableConverter>
</encoder>
</appender>
<!-- Rolling JSON file appender -->
<appender name="JSON_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/${appName}/application.json</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/var/log/${appName}/application.%d{yyyy-MM-dd}.%i.json.gz</fileNamePattern>
<maxHistory>30</maxHistory>
<maxFileSize>100MB</maxFileSize>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<customFields>{"service":"${appName}","version":"${appVersion}"}</customFields>
</encoder>
</appender>
<!-- Text appender for development -->
<appender name="TEXT_CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} %highlight(%-5level) [%thread] %cyan(%logger{36}) - %msg%n</pattern>
</encoder>
</appender>
<!-- Activation by Spring profile -->
<springProfile name="prod,staging">
<root level="INFO">
<appender-ref ref="JSON_CONSOLE"/>
<appender-ref ref="JSON_FILE"/>
</root>
</springProfile>
<springProfile name="dev,local">
<root level="DEBUG">
<appender-ref ref="TEXT_CONSOLE"/>
</root>
</springProfile>
</configuration>Deze configuratie activeert JSON-logs alleen in productie en behoudt leesbare logs tijdens ontwikkeling.
MDC voor distributed tracing
Doorgeven van de tracecontext
MDC (Mapped Diagnostic Context) verrijkt elke log met contextinformatie zoals request- of trace-identificatoren.
// Filter for automatic trace context injection
package com.example.logging.filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.MDC;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
import java.util.UUID;
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class TracingFilter extends OncePerRequestFilter {
// Standard MDC keys for tracing
private static final String TRACE_ID_KEY = "traceId";
private static final String SPAN_ID_KEY = "spanId";
private static final String REQUEST_ID_KEY = "requestId";
private static final String USER_ID_KEY = "userId";
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
try {
// Retrieve or generate trace identifiers
String traceId = extractOrGenerate(request, "X-Trace-Id", TRACE_ID_KEY);
String spanId = generateSpanId();
String requestId = extractOrGenerate(request, "X-Request-Id", REQUEST_ID_KEY);
String userId = request.getHeader("X-User-Id");
// Inject into MDC to appear in all logs
MDC.put(TRACE_ID_KEY, traceId);
MDC.put(SPAN_ID_KEY, spanId);
MDC.put(REQUEST_ID_KEY, requestId);
if (userId != null) {
MDC.put(USER_ID_KEY, userId);
}
// Propagate to responses for inter-service chaining
response.setHeader("X-Trace-Id", traceId);
response.setHeader("X-Request-Id", requestId);
filterChain.doFilter(request, response);
} finally {
// Clean MDC after each request
MDC.clear();
}
}
private String extractOrGenerate(HttpServletRequest request, String header, String key) {
String value = request.getHeader(header);
return value != null ? value : UUID.randomUUID().toString().replace("-", "").substring(0, 16);
}
private String generateSpanId() {
return UUID.randomUUID().toString().replace("-", "").substring(0, 8);
}
}Elke log die tijdens de afhandeling van een request wordt geproduceerd bevat automatisch deze identificatoren.
MDC gebruiken in businesscode
// Business service with enriched contextual logging
package com.example.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.stereotype.Service;
@Service
public class OrderService {
private static final Logger log = LoggerFactory.getLogger(OrderService.class);
public Order createOrder(CreateOrderRequest request) {
// Add business information to MDC context
MDC.put("orderId", request.getOrderId());
MDC.put("customerId", request.getCustomerId());
try {
log.info("Creating order with {} items", request.getItems().size());
// Business logic...
Order order = processOrder(request);
log.info("Order created successfully, total: {} {}",
order.getTotal(), order.getCurrency());
return order;
} catch (Exception e) {
// Exception appears with full MDC context
log.error("Failed to create order", e);
throw e;
} finally {
// Clean business keys added
MDC.remove("orderId");
MDC.remove("customerId");
}
}
}De resulterende JSON-log bevat alle informatie die nodig is voor debugging:
{
"@timestamp": "2026-08-22T10:15:32.456Z",
"level": "INFO",
"logger": "com.example.service.OrderService",
"message": "Order created successfully, total: 150.00 EUR",
"traceId": "a1b2c3d4e5f67890",
"spanId": "12345678",
"requestId": "req-abc-123",
"userId": "user-456",
"orderId": "ORD-789",
"customerId": "CUST-321"
}Klaar om je Spring Boot gesprekken te halen?
Oefen met onze interactieve simulatoren, flashcards en technische tests.
Asynchroon loggen voor performance
Configuratie van de thread pool
In productie beïnvloeden synchrone logschrijfacties de latency van requests. De asynchrone appender ontkoppelt het loggen van de hoofdthread.
<!-- logback-spring.xml -->
<!-- High-performance asynchronous appender configuration -->
<appender name="ASYNC_JSON" class="ch.qos.logback.classic.AsyncAppender">
<!-- Pending log buffer size -->
<queueSize>1024</queueSize>
<!-- Never block the calling thread -->
<neverBlock>true</neverBlock>
<!-- Threshold before dropping DEBUG/TRACE logs -->
<discardingThreshold>20</discardingThreshold>
<!-- Include caller information (expensive) -->
<includeCallerData>false</includeCallerData>
<!-- Actual appender for writing -->
<appender-ref ref="JSON_FILE"/>
</appender>
<springProfile name="prod">
<root level="INFO">
<appender-ref ref="ASYNC_JSON"/>
</root>
</springProfile>Spring Boot 4.1.1 herstelt een kritiek probleem waarbij een mislukte JSON-encode het volgende log event op dezelfde thread kon corrumperen (#51371). Upgrade van 4.0.x of 4.1.0 om stille log-corruptie te vermijden.
Metrics van het loggingsysteem
Het loggingsysteem zelf monitoren voorkomt stille verlies van logs.
// Exposing Logback metrics via Micrometer
package com.example.logging.metrics;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.classic.AsyncAppender;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import jakarta.annotation.PostConstruct;
import java.util.Iterator;
@Component
public class LoggingMetrics {
private final MeterRegistry registry;
public LoggingMetrics(MeterRegistry registry) {
this.registry = registry;
}
@PostConstruct
void registerMetrics() {
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
Logger rootLogger = context.getLogger(Logger.ROOT_LOGGER_NAME);
// Iterate through appenders to find AsyncAppenders
Iterator<Appender<ILoggingEvent>> it = rootLogger.iteratorForAppenders();
while (it.hasNext()) {
Appender<ILoggingEvent> appender = it.next();
if (appender instanceof AsyncAppender asyncAppender) {
registerAsyncMetrics(asyncAppender);
}
}
}
private void registerAsyncMetrics(AsyncAppender appender) {
String appenderName = appender.getName();
// Current queue size
Gauge.builder("logback.async.queue.size", appender, AsyncAppender::getQueueSize)
.tag("appender", appenderName)
.description("Current async appender queue size")
.register(registry);
// Remaining capacity
Gauge.builder("logback.async.queue.remaining", appender, AsyncAppender::getRemainingCapacity)
.tag("appender", appenderName)
.description("Remaining capacity in async queue")
.register(registry);
// Number of dropped logs
Gauge.builder("logback.async.discarded", appender, AsyncAppender::getNumberOfElementsInQueue)
.tag("appender", appenderName)
.description("Number of discarded log events")
.register(registry);
}
}Een Prometheus-alert op logback.async.queue.remaining < 100 waarschuwt voor het risico op verlies van logs.
Integratie met ELK Stack
Filebeat-configuratie
Filebeat verzamelt de JSON-bestanden en stuurt ze zonder transformatie naar Elasticsearch.
# filebeat.yml
# Filebeat configuration for Spring Boot JSON logs
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/*/application.json
# Automatic JSON parsing
json:
keys_under_root: true
overwrite_keys: true
add_error_key: true
message_key: message
processors:
# Add Kubernetes metadata if available
- add_kubernetes_metadata:
host: ${NODE_NAME}
matchers:
- logs_path:
logs_path: "/var/log/containers/"
# Parse timestamp
- timestamp:
field: "@timestamp"
layouts:
- '2006-01-02T15:04:05.000Z'
- '2006-01-02T15:04:05.000-07:00'
test:
- '2026-08-22T10:15:32.456Z'
output.elasticsearch:
hosts: ["elasticsearch:9200"]
index: "logs-%{[service]}-%{+yyyy.MM.dd}"
pipeline: "spring-boot-logs"
setup.template:
name: "logs"
pattern: "logs-*"Elasticsearch-pipeline voor verrijking
{
"description": "Spring Boot logs enrichment",
"processors": [
{
"geoip": {
"field": "client.ip",
"target_field": "client.geo",
"ignore_missing": true
}
},
{
"user_agent": {
"field": "user_agent.original",
"target_field": "user_agent",
"ignore_missing": true
}
},
{
"set": {
"field": "event.ingested",
"value": "{{_ingest.timestamp}}"
}
},
{
"script": {
"description": "Classify log level severity",
"source": "def level = ctx.level; if (level == 'ERROR') ctx.severity = 4; else if (level == 'WARN') ctx.severity = 3; else if (level == 'INFO') ctx.severity = 2; else ctx.severity = 1;"
}
}
]
}Best practices in productie voor Spring Boot logging
Informatie die systematisch moet worden opgenomen
Elke log moet een minimum aan informatie bevatten voor debugging en correlatie.
// Helper for consistent structured logs
package com.example.logging;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import java.util.Map;
import java.util.function.Supplier;
public final class StructuredLogger {
private final Logger delegate;
private StructuredLogger(Class<?> clazz) {
this.delegate = LoggerFactory.getLogger(clazz);
}
public static StructuredLogger getLogger(Class<?> clazz) {
return new StructuredLogger(clazz);
}
// Log with temporary business context
public void info(String message, Map<String, String> context) {
try {
context.forEach(MDC::put);
delegate.info(message);
} finally {
context.keySet().forEach(MDC::remove);
}
}
// Log with supplier for lazy evaluation
public void debug(Supplier<String> messageSupplier, Map<String, String> context) {
if (delegate.isDebugEnabled()) {
try {
context.forEach(MDC::put);
delegate.debug(messageSupplier.get());
} finally {
context.keySet().forEach(MDC::remove);
}
}
}
// Error log with full context
public void error(String message, Throwable t, Map<String, String> context) {
try {
context.forEach(MDC::put);
delegate.error(message, t);
} finally {
context.keySet().forEach(MDC::remove);
}
}
}// Usage in business code
private static final StructuredLogger log = StructuredLogger.getLogger(PaymentService.class);
public void processPayment(Payment payment) {
log.info("Processing payment", Map.of(
"paymentId", payment.getId(),
"amount", String.valueOf(payment.getAmount()),
"currency", payment.getCurrency(),
"method", payment.getMethod().name()
));
}Gevoelige informatie die uitgesloten moet worden
Logs mogen nooit persoonsgegevens of gevoelige data bevatten.
// Sensitive data masking utility
package com.example.logging.filter;
import java.util.regex.Pattern;
public final class SensitiveDataFilter {
// Sensitive data patterns to mask
private static final Pattern EMAIL_PATTERN =
Pattern.compile("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}");
private static final Pattern CREDIT_CARD_PATTERN =
Pattern.compile("\\b\\d{4}[- ]?\\d{4}[- ]?\\d{4}[- ]?\\d{4}\\b");
private static final Pattern PASSWORD_PATTERN =
Pattern.compile("(?i)(password|pwd|secret|token)[\"']?\\s*[:=]\\s*[\"']?[^\\s,}\"']+");
private SensitiveDataFilter() {}
// Utility method to mask data
public static String maskSensitiveData(String input) {
if (input == null) return null;
String result = input;
result = EMAIL_PATTERN.matcher(result).replaceAll("[EMAIL_MASKED]");
result = CREDIT_CARD_PATTERN.matcher(result).replaceAll("[CARD_MASKED]");
result = PASSWORD_PATTERN.matcher(result).replaceAll("$1=[REDACTED]");
return result;
}
}Geschikte logniveaus
| Niveau | Toepassing | Voorbeelden |
|---|---|---|
| ERROR | Fout die ingrijpen vereist | Onherstelbare exceptions, kritieke transactiefouten, externe services niet beschikbaar |
| WARN | Abnormale maar afgehandelde situatie | Retry bezig, performance-degradatie, resources nabij limieten |
| INFO | Significante business events | Start/einde transactie, belangrijke statuswijzigingen, belangrijke gebruikersacties |
| DEBUG | Diagnostische informatie | Uitvoeringsdetails, belangrijke variabelewaarden, branching-beslissingen |
| TRACE | Zeer fijne details | Methode entry/exit, volledige objectinhoud, loops en iteraties |
Tests en validatie van gestructureerde logs
Unit tests op de JSON-structuur
// Structured log validation tests
package com.example.logging;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.read.ListAppender;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import static org.assertj.core.api.Assertions.assertThat;
class StructuredLoggingTest {
private ListAppender<ILoggingEvent> listAppender;
private Logger logger;
@BeforeEach
void setUp() {
logger = (Logger) LoggerFactory.getLogger(StructuredLoggingTest.class);
listAppender = new ListAppender<>();
listAppender.start();
logger.addAppender(listAppender);
}
@Test
void shouldIncludeMdcFieldsInLog() {
// Given
MDC.put("traceId", "test-trace-123");
MDC.put("userId", "user-456");
// When
logger.info("Test message with MDC context");
// Then
ILoggingEvent event = listAppender.list.get(0);
assertThat(event.getMDCPropertyMap())
.containsEntry("traceId", "test-trace-123")
.containsEntry("userId", "user-456");
MDC.clear();
}
@Test
void shouldLogExceptionWithStackTrace() {
// Given
Exception testException = new RuntimeException("Test error");
// When
logger.error("Operation failed", testException);
// Then
ILoggingEvent event = listAppender.list.get(0);
assertThat(event.getThrowableProxy()).isNotNull();
assertThat(event.getThrowableProxy().getMessage()).isEqualTo("Test error");
}
}Voor integration testing patterns die goed werken met gestructureerde logging, zie de Testcontainers Spring Boot integration testing gids.
Sources
- Spring Boot 4.1.0 Release Announcement - Spring Boot 4.1.0 features inclusief observability updates
- Spring Boot GitHub Releases - Versie 4.1.1 bugfix voor JSON encode corruptie (#51371)
- Logstash Logback Encoder 9.0 - Jackson 3 migratie en Java 17 vereiste
- OpenTelemetry with Spring Boot - Officiële OpenTelemetry integratiegids
Checklist voor gestructureerde logging in Spring Boot 4.x
- Native gestructureerde logging met ECS-, Logstash- of GELF-formaat vereist alleen
logging.structured.formatconfiguratie - De
spring-boot-starter-opentelemetryvervangt legacy Sleuth setups door vendor-neutrale observability - MDC propageert trace-identificatoren automatisch tussen services
- Asynchrone appenders met
neverBlock=truevoorkomen dat logging de request latency beïnvloedt - Logstash Logback Encoder 9.0 vereist Jackson 3.0 en Java 17
- Spring Boot 4.1.1 herstelt een kritieke JSON encoding bug die concurrent threads beïnvloedde
- Maskering van gevoelige data waarborgt AVG-conformiteit in productie logs
- Metrics op async queue capaciteit maken alerting mogelijk voordat logs verloren gaan
Begin met oefenen!
Test je kennis met onze gespreksimulatoren en technische tests.
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 22 augustus 2026
Tags
Delen
Gerelateerde artikelen

Spring Boot Actuator: Productie-Monitoring met Micrometer en Prometheus
Volledige Spring Boot Actuator gids voor productie-monitoring. Micrometer-configuratie, Prometheus-metrieken, custom endpoints en alerting.

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 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.