Spring Boot: From Basics to Production · Observability with Actuator and Micrometer
Structured Logging
Emit JSON logs with context for log aggregation.
Spring Boot 3.4+ supports structured logging natively: set logging.structured.format.console to ecs, gelf or logstash to emit JSON with trace IDs and MDC values. Use SLF4J parameterized logging, add context with MDC (request ID, tenant), log at appropriate levels, and never log secrets or full request bodies.
@Component
class TenantMdcFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
throws ServletException, IOException {
try {
MDC.put("tenant", req.getHeader("X-Tenant-Id"));
chain.doFilter(req, res);
} finally {
MDC.remove("tenant");
}
}
}
@Service
class OrderService {
private static final Logger log = LoggerFactory.getLogger(OrderService.class);
void cancel(long orderId, String reason) {
log.info("Order cancelled orderId={} reason={}", orderId, reason); // parameterized
}
}
logging:
structured:
format:
console: ecs
level:
com.example.shop: INFO
Common pitfalls
- String concatenation in log calls (wasted work when level is disabled).
- Not clearing MDC in thread pools (context leaks to other requests).
- Logging tokens, passwords or full payloads.
Key points
- Native JSON logging (ECS/GELF/Logstash)
- MDC for request context; always clear it
- Parameterized messages, no secrets
Further reading: Spring Boot: Structured logging
Practice questions
Why must MDC values be removed in a finally block?
Answer
Servlet threads are pooled; leftover MDC values would appear in logs of unrelated later requests handled by the same thread.
What's the advantage of structured (JSON) logs?
Answer
Log platforms can index and query fields (traceId, tenant, orderId) reliably, without fragile text parsing.
Open in the app to mark lessons complete, take notes and track your progress.