Mastering Logback in Spring Boot: From Basics to Advanced Configuration
This guide walks through the fundamentals and advanced usage of Logback in Spring Boot, covering its architecture, default integration, Maven dependencies, XML and property configurations, custom appenders, asynchronous logging, MDC for distributed tracing, and ELK integration with practical code examples.
Introduction
Older projects often mix logging frameworks such as Log4j and Logback, leading to inconsistency. Since Spring Boot bundles Logback as the default logging implementation, a unified understanding is essential.
Logback Overview
Logback is the successor of Log4j, offering better performance, smaller size, and greater flexibility. It consists of three modules: logback-core, logback-classic (which implements the SLF4J façade), and logback-access (for servlet‑container integration).
Typical usage only requires adding the logback-classic dependency, which transitively pulls in logback-core.
Spring Boot Integration
Spring Boot automatically includes Logback via the spring-boot-starter-web starter. Adding this starter brings in Logback, SLF4J, and related libraries, so no extra configuration is needed to start logging.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>A simple controller can log at different levels:
@RestController
public class HelloWorldController {
private static final Logger log = LoggerFactory.getLogger(HelloWorldController.class);
@RequestMapping("/hello")
public void hello() {
log.debug("Hello world test debug");
log.info("Hello world test info");
log.warn("Hello world test warn");
log.error("Hello world test error");
}
}By default Spring Boot logs at INFO level, so only INFO, WARN and ERROR appear. To enable DEBUG output, add the following to application.properties:
logging.level.com.secbro2=debugBasic Property Configuration
Spring Boot writes logs to the console by default. To log to a file, set either logging.file (absolute or relative file name) or logging.path (directory, which creates spring.log inside it). These two properties are mutually exclusive.
# file name (absolute or relative)
logging.file=my.log
# directory path (creates spring.log)
logging.path=/var/logOther common properties include package‑specific levels ( logging.level.com.example=DEBUG) and pattern customisation ( logging.pattern.console).
Custom XML Configuration (logback‑spring.xml)
For complex scenarios, place an XML file named logback-spring.xml (or logback.xml) under src/main/resources. Spring Boot prefers the -spring variant because it allows property substitution.
The core elements are:
configuration : root element, may contain debug, scan, scanPeriod attributes.
appender : defines where and how logs are written (ConsoleAppender, FileAppender, RollingFileAppender, etc.).
logger : sets level and appender for a specific package or class.
root : the fallback logger for all unspecified categories.
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="chapters.configuration" level="INFO"/>
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
</root>
</configuration>Configuration Attributes
debug="true": prints Logback’s internal status messages. scan="true" and scanPeriod="30 seconds": automatically reload the file when it changes.
Context Name and Properties
Define a context name for multi‑application environments:
<configuration>
<contextName>HelloWorld-log</contextName>
</configuration>Define reusable variables with property elements:
<property name="log.path" value="./log"/>Appender Examples
ConsoleAppender (default) and RollingFileAppender (file rotation) are most common. A RollingFileAppender can be configured with a time‑based policy:
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/debug.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/debug.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>Logger and Root Configuration
Set package‑specific levels and associate them with appenders:
<logger name="com.secbro2" level="info" additivity="true">
<appender-ref ref="CONSOLE"/>
</logger>
<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="LOGSTASH"/>
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="ERROR_FILE"/>
</root>Multiple springProfile sections allow different logging setups per environment (dev, test, prod).
<springProfile name="dev">
<logger name="com" level="debug"/>
<root level="info">
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>
<springProfile name="test,prod">
<logger name="com" level="info"/>
<root level="info">
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="ERROR_FILE"/>
</root>
</springProfile>ELK Integration
To ship logs to Logstash, add the logstash-logback-encoder dependency and configure a TCP socket appender:
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>5.1</version>
</dependency> <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<destination>192.168.0.11:5061</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
<customFields>{"project":"springboot-logback-elk"}</customFields>
</encoder>
</appender>Asynchronous Logging
Use AsyncAppender to avoid blocking I/O in high‑throughput applications:
<appender name="ASYNCDEBUG" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>1024</queueSize>
<appender-ref ref="DEBUGFILE"/>
<includeCallerData>true</includeCallerData>
</appender>
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNCDEBUG"/>
</root>MDC for Distributed Tracing
In micro‑service environments, propagate a request identifier using Logback’s MDC. A UUID generator and a Spring HandlerInterceptor store the ID in MDC before the request and remove it after completion.
public class IdUtil {
public static String simpleUuid() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
} @Component
public class RequestIdTraceInterceptor implements HandlerInterceptor {
private static final String REQUEST_ID_KEY = "request-id";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
MDC.put(REQUEST_ID_KEY, getRequestId(request));
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
response.addHeader(REQUEST_ID_KEY, MDC.get(REQUEST_ID_KEY));
MDC.remove(REQUEST_ID_KEY);
}
public static String getRequestId(HttpServletRequest request) {
String param = request.getParameter(REQUEST_ID_KEY);
String header = request.getHeader(REQUEST_ID_KEY);
return (param == null && header == null) ? IdUtil.simpleUuid() : (param != null ? param : header);
}
}Register the interceptor via WebMvcConfigurer:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Resource
private RequestIdTraceInterceptor requestIdTraceInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(requestIdTraceInterceptor);
}
}Expose the ID in the log pattern with %X{request-id}:
<property name="CONSOLE_LOG_PATTERN" value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) [%X{request-id}] %clr(%logger){cyan} - %msg%n"/>Best Practices
Prefer parameterised logging ( log.debug("Message {}", obj)) to avoid unnecessary string concatenation when the log level is disabled.
Use Lombok’s @Slf4j annotation to inject a logger automatically.
Configure separate appenders for console, INFO+, and ERROR to simplify troubleshooting.
Conclusion
Logback provides a powerful, flexible logging solution for Spring Boot applications. By mastering its core modules, default Spring Boot integration, property‑based and XML configurations, custom appenders, asynchronous output, MDC tracing, and ELK shipping, developers can achieve clean, performant, and observable logging across both monolithic and distributed systems.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Senior Brother's Insights
A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
