4.3 Logging with SLF4J & Logback
← Back to Chapter 4: Exception Handling, Logging & Production Support
Production microservices require structured, efficient, and traceable logs. Spring Boot utilizes SLF4J (Simple Logging Facade for Java) backed by Logback by default.
Logging
Logging means recording what is happening inside the application.
For example:
Customer verification started
Customer ID = C123
Verification request sent
Government API response received
Verification completed
Logs help developers and support teams understand what happened.
Logging Levels
The major logging levels are:
TRACE
DEBUG
INFO
WARN
ERROR
From less severe to more severe:
TRACE
↓
DEBUG
↓
INFO
↓
WARN
↓
ERROR
1. Logging Levels & Thresholds
TRACE < DEBUG < INFO < WARN < ERROR < OFF
▲ ▲
Verbose execution details System failures
TRACE: Low-level step-by-step method and query traces.DEBUG: Diagnostic data valuable during development and troubleshooting.INFO: High-level operational events (service startup, batch job completed).WARN: Potential issues (slow database query, retry triggered, deprecated API hit).ERROR: Actionable faults requiring engineer investigation.
Configuring Levels in application.yml:
logging:
level:
root: INFO
org.springframework.web: WARN
org.hibernate.SQL: DEBUG
com.codewithsarvy: DEBUG
2. Structured Logging with MDC (Mapped Diagnostic Context)
In multi-threaded and distributed systems, tracing requests across concurrent threads is impossible without a unique correlation identifier. Logback's MDC stores thread-local contextual data:
@Component
public class CorrelationIdFilter extends OncePerRequestFilter {
public static final String CORRELATION_ID_KEY = "correlationId";
public static final String CORRELATION_ID_HEADER = "X-Correlation-Id";
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
String correlationId = request.getHeader(CORRELATION_ID_HEADER);
if (correlationId == null || correlationId.isBlank()) {
correlationId = UUID.randomUUID().toString();
}
try {
MDC.put(CORRELATION_ID_KEY, correlationId);
response.setHeader(CORRELATION_ID_HEADER, correlationId);
chain.doFilter(request, response);
} finally {
MDC.remove(CORRELATION_ID_KEY); // Mandatory to prevent thread pool leakage!
}
}
}
3. Logback Configuration (logback-spring.xml)
For production environments (e.g., streaming to Elasticsearch / Splunk / Datadog), JSON logging is standard:
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{correlationId}] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>
SLF4J
In Spring Boot applications, you'll commonly see:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Example:
private static final Logger log =
LoggerFactory.getLogger(CustomerService.class);
public void verifyCustomer(String customerId) {
log.info("Starting verification for customerId={}", customerId);
try {
// verification logic
} catch (Exception ex) {
log.error("Verification failed for customerId={}",
customerId, ex);
throw ex;
}
}
Why Use SLF4J?
SLF4J is a logging abstraction.
It allows your application code to use a common logging API while the actual logging implementation can be something like Logback.
In Spring Boot, Logback is commonly used by default with the standard logging setup.
SLF4J provides a common logging API, and Spring Boot commonly uses Logback as the underlying logging implementation.