Configuring Logback
Appenders, patterns, and levels.
Configuring Logback is a free Java Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Is Logback?
Logback is a popular SLF4J backend, written by the same author as Log4j. It actually performs the logging that SLF4J calls describe.
You configure it with a file named logback.xml on the classpath, usually under src/main/resources.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.info("Logback reads logback.xml at startup");
}
}Three Building Blocks
Logback config has three core concepts:
- Logger: named source of log events, with a level.
- Appender: a destination (console, file).
- Encoder/Layout: formats the event into text.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.info("logger -> appender -> encoder -> output");
}
}A Console Appender
The simplest config sends everything to the console. The encoder's pattern controls the line format.
This XML lives in logback.xml, not in your Java code.
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>Understanding the Pattern
Pattern conversion words start with %:
%dtimestamp,%levelthe level.%loggerthe logger name,%threadthe thread.%msgyour message,%na newline.
%-5level left-pads the level to width 5.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
// Output rendered by pattern: time LEVEL logger - message
log.info("hello");
}
}The Root Logger and Levels
The <root> element sets the default level for the whole app and which appenders it writes to.
Setting level="info" means INFO, WARN, and ERROR are emitted; DEBUG and TRACE are suppressed.
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder><pattern>%-5level %logger - %msg%n</pattern></encoder>
</appender>
<root level="warn">
<appender-ref ref="STDOUT" />
</root>
</configuration>Per-Package Levels
Add a <logger> element to override the level for a package. This lets you enable DEBUG for your own code while keeping libraries quiet.
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder><pattern>%-5level %logger - %msg%n</pattern></encoder>
</appender>
<logger name="com.example.app" level="debug" />
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>A Rolling File Appender
For production you usually write to files that roll over daily or by size, so logs do not grow without bound.
RollingFileAppender with a time-based policy creates one file per day and keeps a capped history.
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/app.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d %-5level [%thread] %logger{36} - %msg%n</pattern>
</encoder>
</appender>Multiple Appenders at Once
The root logger can reference several appenders, so logs go to both console and file simultaneously.
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder><pattern>%-5level %msg%n</pattern></encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>logs/app.log</file>
<encoder><pattern>%d %-5level %msg%n</pattern></encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>Printing the MDC
To include MDC context like a request id on every line, add %X{key} to the pattern.
Then any value you put in the MDC appears automatically.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
MDC.put("requestId", "req-1234");
// Pattern: %X{requestId} %-5level %msg%n
log.info("handled");
MDC.clear();
}
}Additivity
By default a logger's events also go to its ancestors' appenders. This is additivity.
If a package logger has its own appender and you do not want duplicate output, set additivity="false" on it.
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder><pattern>%-5level %logger - %msg%n</pattern></encoder>
</appender>
<logger name="com.example.audit" level="info" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
<root level="warn">
<appender-ref ref="STDOUT" />
</root>
</configuration>Auto-Reload and Variables
Logback can reload config periodically with <configuration scan="true">, useful for changing levels without a restart.
You can also read properties, such as a log directory, with ${LOG_DIR} placeholders.
<configuration scan="true" scanPeriod="30 seconds">
<property name="LOG_DIR" value="logs" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${LOG_DIR}/app.log</file>
<encoder><pattern>%d %-5level %msg%n</pattern></encoder>
</appender>
<root level="info"><appender-ref ref="FILE" /></root>
</configuration>Quick Check
Test your Logback configuration knowledge.
Recap
You learned to configure Logback:
- Config lives in
logback.xmlwith loggers, appenders, and encoders. - Patterns format lines with
%d,%level,%msg,%X{}. - RollingFileAppender rotates logs; set per-package levels and additivity.
- Enable
scanfor live reconfiguration.
You have completed the logging course.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.info("Logback configuration course complete");
}
}Frequently asked questions
Is the “Configuring Logback” lesson free?
Yes — the full text of “Configuring Logback” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.
What will I learn in “Configuring Logback”?
Appenders, patterns, and levels. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Java Academy?
No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Configuring Logback” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Java Academy lesson?
Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Why Structured Logging
- SLF4J Facade and Loggers
- Parameterized Logging
- Configuring Logback