Logs estructurados en Spring Boot 2026: JSON para producción con Logback y OpenTelemetry
Guía completa de logs estructurados en Spring Boot 4.x. Soporte JSON nativo, starter OpenTelemetry, tracing MDC e integración ELK Stack para observabilidad en producción.

Los logs tradicionales en formato texto se vuelven inmanejables rápidamente en producción. Con cientos de instancias generando miles de líneas por segundo, buscar un error específico se convierte en una pesadilla. Los logs estructurados en JSON transforman esta situación al hacer que cada evento sea consultable y analizable de forma automática.
Spring Boot 4.x (construido sobre Spring Framework 7) soporta de forma nativa el logging estructurado en JSON con formatos ECS, Logstash y GELF. El nuevo spring-boot-starter-opentelemetry proporciona observabilidad unificada sin dependencias externas.
Por qué adoptar logs estructurados en Spring Boot
Limitaciones de los logs en texto plano
Un log de texto típico tiene este aspecto:
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: 3Este formato presenta varios problemas en producción. Extraer información específica requiere expresiones regulares complejas y frágiles. La correlación entre servicios exige convenciones estrictas que cada equipo interpreta a su manera. Las herramientas de análisis como Elasticsearch tienen dificultades para indexar eficientemente estas cadenas no estructuradas.
Ventajas del formato JSON
El mismo evento en JSON resulta inmediatamente explotable:
{
"@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
}Cada campo se vuelve filtrable y agregable. Una consulta Elasticsearch encuentra al instante todos los pedidos superiores a 100€ de los últimos quince minutos. Los dashboards de Kibana visualizan tendencias sin parsing manual. Esta competencia es particularmente relevante en las preguntas de entrevista Spring Boot, donde comprender los patrones de observabilidad en producción distingue a los candidatos senior.
Configuración nativa de logs estructurados en Spring Boot 4.x
Activar los logs JSON estructurados
Spring Boot 4.x, construido sobre Spring Framework 7, introduce soporte maduro para logging estructurado mediante la propiedad logging.structured. Este enfoque no requiere ninguna dependencia adicional y se integra directamente con 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: DEBUGEl formato ECS (Elastic Common Schema) garantiza compatibilidad directa con Elasticsearch y Kibana sin configuración adicional.
Personalizar los campos JSON
Para añadir campos de negocio en cada log, Spring Boot permite configurar atributos adicionales.
# 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);
}
}Estos campos aparecen en cada línea de log y facilitan el filtrado por equipo o región en los dashboards.
OpenTelemetry Starter para observabilidad completa
El nuevo estándar en Spring Boot 4
Spring Boot 4.0 introdujo spring-boot-starter-opentelemetry, reemplazando la configuración multi-dependencias que existía anteriormente. Esta única dependencia proporciona observabilidad vendor-neutral incluyendo trazas, métricas y correlación de logs.
<!-- 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>Este starter incluye la API de OpenTelemetry, el bridge de Micrometer tracing y los exportadores OTLP. Spring Cloud Sleuth ahora se considera legacy, siendo OpenTelemetry el estándar de la industria para tracing distribuido.
Configuración OpenTelemetry con logs estructurados
# 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:-}]"Los identificadores de trace y span se inyectan automáticamente en el MDC, correlacionando los logs con las trazas distribuidas entre servicios. Para más información sobre configuraciones de monitoreo en producción, consulta la guía de Spring Boot Actuator con Micrometer y Prometheus.
ZipkinWithOpenTelemetryTracingAutoConfiguration está deprecada y programada para eliminación en Spring Boot 4.2. Se recomienda migrar a exportadores OTLP nativos para compatibilidad futura.
Configuración clásica de Logback con encoder JSON
Logstash Encoder para personalización avanzada
Para necesidades de personalización avanzada o al migrar desde versiones anteriores de Spring Boot, Logstash Logback Encoder 9.0 sigue disponible. La versión 9.0 requiere Jackson 3.0 y Java 17 como mínimo.
<!-- 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>Configuración Logback completa
El archivo logback-spring.xml ofrece control total sobre el formato de salida.
<!-- 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>Esta configuración activa los logs JSON únicamente en producción y conserva logs legibles en desarrollo.
MDC para tracing distribuido
Propagación del contexto de trace
MDC (Mapped Diagnostic Context) enriquece cada log con información de contexto como los identificadores de petición o de trace.
// 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);
}
}Cada log emitido durante el procesamiento de la petición contendrá automáticamente estos identificadores.
Uso de MDC en código de negocio
// 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");
}
}
}El log JSON resultante contiene toda la información necesaria para el 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"
}¿Listo para aprobar tus entrevistas de Spring Boot?
Practica con nuestros simuladores interactivos, flashcards y tests técnicos.
Logging asíncrono para rendimiento
Configuración del thread pool
En producción, las escrituras síncronas de logs impactan la latencia de las peticiones. El appender asíncrono desacopla el logging del hilo principal.
<!-- 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 corrigió un problema crítico donde un fallo en el encode JSON podía corromper el siguiente evento de log en el mismo thread (#51371). Se recomienda actualizar desde 4.0.x o 4.1.0 para evitar corrupción silenciosa de logs.
Métricas del sistema de logging
Monitorear el propio sistema de logging evita la pérdida silenciosa de 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);
}
}Una alerta Prometheus sobre logback.async.queue.remaining < 100 advierte de los riesgos de pérdida de logs.
Integración con ELK Stack
Configuración de Filebeat
Filebeat recoge los archivos JSON y los envía a Elasticsearch sin transformación.
# 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-*"Pipeline Elasticsearch para enriquecimiento
{
"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;"
}
}
]
}Mejores prácticas para producción en Spring Boot
Información que debe incluirse de forma sistemática
Cada log debe contener un mínimo de información para el debugging y la correlación.
// 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()
));
}Información sensible que debe excluirse
Los logs nunca deben contener datos personales o sensibles.
// 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;
}
}Niveles de log adecuados
| Nivel | Caso de uso | Ejemplos |
|---|---|---|
| ERROR | Fallo que requiere intervención | Excepciones no recuperables, fallos críticos de transacciones, indisponibilidad de servicios externos |
| WARN | Situación anormal pero manejada | Reintento en progreso, degradación de rendimiento, recursos cerca de los límites |
| INFO | Eventos de negocio significativos | Inicio/fin de transacciones, cambios de estado importantes, acciones clave del usuario |
| DEBUG | Información de diagnóstico | Detalles de ejecución, valores de variables importantes, decisiones de ramificación |
| TRACE | Detalles muy finos | Entrada/salida de métodos, contenido completo de objetos, bucles e iteraciones |
Pruebas y validación de logs estructurados
Tests unitarios sobre la estructura JSON
// 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");
}
}Para patrones de testing de integración que funcionan bien con logs estructurados, consulta la guía de integración de Testcontainers con Spring Boot.
Fuentes
- Anuncio de Spring Boot 4.1.0 - Características de Spring Boot 4.1.0 incluyendo actualizaciones de observabilidad
- Releases en GitHub de Spring Boot - Versión 4.1.1 corrección de bug de codificación JSON (#51371)
- Logstash Logback Encoder 9.0 - Migración a Jackson 3 y requisito de Java 17
- OpenTelemetry con Spring Boot - Guía oficial de integración de OpenTelemetry
Checklist de logs estructurados para Spring Boot 4.x
- El logging estructurado nativo con formato ECS, Logstash o GELF solo requiere la configuración
logging.structured.format - El
spring-boot-starter-opentelemetryreemplaza las configuraciones legacy de Sleuth con observabilidad vendor-neutral - MDC propaga automáticamente los identificadores de trace entre servicios
- Los appenders asíncronos con
neverBlock=trueevitan impactar la latencia de las peticiones - Logstash Logback Encoder 9.0 requiere Jackson 3.0 y Java 17
- Spring Boot 4.1.1 corrigió un bug crítico de codificación JSON que afectaba a threads concurrentes
- El enmascaramiento de datos sensibles garantiza el cumplimiento del RGPD en logs de producción
- Las métricas sobre la capacidad de la cola async permiten alertar antes de perder logs
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
¿Sabrías detectar el bug en Spring Boot?
Un fragmento real, un bug oculto, un intento al día. Sin cuenta para probar.

Escrito por
Anthony Fillion-MailletFundador de SharpSkill
Desarrollador fullstack desde hace más de 10 años. Dirige SharpSkill y responde por todo lo que se publica aquí.
Actualizado el 22 de agosto de 2026
Etiquetas
Compartir
Artículos relacionados

Observabilidad en Spring Boot 2026: OpenTelemetry, Tracing Distribuido y Preguntas de Entrevista
Guía completa sobre observabilidad en Spring Boot con OpenTelemetry y tracing distribuido. Configuración OTLP, Observation API, propagación de contexto y preguntas técnicas para entrevistas backend.

Spring Boot Actuator: Monitoreo en Producción con Micrometer y Prometheus
Guía completa de Spring Boot Actuator para monitoreo en producción. Configuración Micrometer, métricas Prometheus, endpoints personalizados y alertas.

Spring Boot YAML vs Properties: Comparacion de Configuracion y Preguntas de Entrevista 2026
Comparacion detallada entre YAML y Properties en Spring Boot. Sintaxis, gestion de perfiles, estructuras de datos y preguntas de entrevista tecnica.