Getting started with the logback logging library
Logback is a known Java logging library and an alternative to the better-known log4j library. I already wrote about an “advanced” feature of logback in a previous article. In this article, I will provide a practical introduction so you can start quickly and easily with logback.
Logback and SLF4J
Logback is directly related to SLF4J, a logging “facade” library that is very popular in Java because many frameworks and libraries use it. SLF4J provides a great abstraction layer on top of several different logging libraries.
When you use SLF4J, your application is only tightly coupled to the SLF4J API, not to classes of a specific logging library like logback or log4j. This aspect has the significant advantage that, at any time, you can easily change the underlying logging library without changing any code in your application (clearly, except for logging-specific configuration).
SLF4J has the concept of logging “backend”, an artifact that bridges the SLF4J API and a concrete logging library like log4j. However, logback does not need an external logging backend since it already provides the backend for SLF4J.
Logback dependencies
You can easily use logback in a Maven/Gradle project. This article mainly focuses on how to use logback in a simple Java SE application, while for any advanced framework, please consult the related documentation. For example, if you use Spring Boot, logback is automatically used by default unless you explicitly opt for another logging library.
Issues with SLF4J versions
Before seeing the details about dependencies, we must discuss an issue about SLF4J. Recently, SLF4J has been updated to version 2.x, which brings some new features. One critical change in SLF4J 2.x is the new lookup strategy for finding a logging backend using the well-known ServiceLoader mechanism. Please, read my previous article, “The new features of SLF4J 2.x”.
Logback has been updated as well to use SLF4J 2.x. However, nowadays, depending on the logback version, you must pay close attention to the SLF4J and Java versions. The following table should provide a clear overview of logback and the required Java and SLF4J versions.
Logback version | Java version | SLF4J version |
---|---|---|
< 1.3.0 | Java 6+ | 1.x |
≥ 1.3.0 and < 1.4.0 | Java 8+ | 2.x |
≥ 1.4.0 | Java 11+ | 2.x |
Try to avoid mixing inconsistent logback and SLF4J versions! For example, logback 1.2.12 does not work with SLF4J 2.x, and logback 1.3.6 does not work with SLF4J 1.x.
Maven dependencies
In a Maven project, you generally only need one dependency to use logback:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.6</version>
</dependency>
See the equivalent Gradle dependency on the Maven Central repository.
The logback-classic
artifact has two transitive dependencies, as depicted below:
logback-classic : 1.4.6
│
├── logback-core : 1.4.6
│
└── slf4j-api : 2.0.4
Note that in logback, the SLF4J “backend” is contained in the logback-classic
artifact. Thus, to be clear and precise, the logback-core
artifact alone is not sufficient to use logback through SLF4J. If logback seems not to work in your application, ensure that you have both the logback-classic
and the logback-core
artifacts (plus the slf4j-api
artifact, clearly).
You may eventually upgrade the SLF4J API version in some situations. For example, logback 1.4.6 uses SLF4J 2.0.4, but to date (as of April 2023), there is already SLF4J 2.0.7. So you can use the following:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.6</version>
</dependency>
Since the explicit slf4j-api
dependency is closer to the project, it “wins” over the transitive dependency from the logback-classic
artifact. Note that you can place the slf4j-api
dependency before or after the logback-classic
dependency. It doesn’t matter for Maven in this case.
Logback configuration
Logback can be configured in a few different ways. “Chapter 3: Logback configuration” of the logback manual provides an excellent description of the initialization process.
Except for particular or complex scenarios, at the basic level, you just need to know that logback searches for two specific configuration files at the “root” of the classpath and precisely in the following order:
logback-test.xml
logback.xml
The logback-test.xml
file helps override the configuration during unit testing of the application. Instead, logback.xml
is the “standard” configuration file that the application typically uses. In a conventional Maven/Gradle project, these configuration files are normally located under the following paths:
- <project-name>
/src/main/resources/logback.xml
- <project-name>
/src/test/resources/logback-test.xml
Remember that when you run unit tests, logback picks up the logback-test.xml
instead of the logback.xml
. If logback-test.xml
were not present, then logback fallbacks to use logback.xml
also for unit tests. On the contrary, when the application runs, logback picks up the logback.xml
because test classes and test resources are usually not considered nor packaged with the application.
Configuration examples
The following is a basic configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%date{HH:mm:ss.SSS} [%thread] %-5level %logger{30} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
You may find a similar but slightly simpler configuration file like the following on the internet, especially on (old) articles or Java projects:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{HH:mm:ss.SSS} [%thread] %-5level %logger{30} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
This latter is a “legacy” configuration format still valid today.
The pattern used in the configurations above is a very simple one. You can change the pattern as you like; the official documentation describes all the available conversion words at PatternLayout.
From the configurations above, you can deduce the following things:
- A single appender named
STDOUT
writes to the console (standard output by default) using the specified pattern. - The “root” logger uses the
INFO
level. It means that onlyINFO
,WARN
, andERROR
levels are enabled while TRACE and DEBUG levels are disabled. - The “root” logger sends log events to the appender named
STDOUT
, previously defined.
You can add more specific loggers using the <logger>
tag like the following:
<logger name="your.pkgname" level="DEBUG"/>
<logger name="your.pkgname.ClassName" level="TRACE"/>
Example Java code
With the information provided so far, you can write a simple Java class to test if logback works as expected.
package your.pkgname;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogSample {
private static final Logger logger = LoggerFactory.getLogger(LogSample.class);
public static void main(String[] args) {
logger.trace("This is a message at trace level");
logger.debug("This is a message at debug level");
logger.info("This is a message at info level");
logger.warn("This is a message at warn level");
logger.error("This is a message at error level");
}
}
The reference to the Logger
object for a class is typically held in a private static final
field that is generally named “logger
” or sometimes “log
”. Note also that, as stated before, the code only uses the SLF4J API (package org.slf4j
), not logback-specific classes.
Furthermore, if your project also uses Lombok (a famous annotation-based code generation tool), you can use the
@Slf4j
annotation on your class. Lombok generates for you thatprivate static final
field named “log
” by default (the field name can be customized). Just for reference:import lombok.extern.slf4j.Slf4j; @Slf4j public class YourClass { // ... }
With the Java code above and the logback.xml
configuration file previously shown (either the new or the “legacy” format), you should obtain an output similar to the following when you run the LogSample
class:
18:39:59.463 [main] INFO your.pkgname.LogSample - This is a message at info level
18:39:59.463 [main] WARN your.pkgname.LogSample - This is a message at warn level
18:39:59.463 [main] ERROR your.pkgname.LogSample - This is a message at error level
Conclusions
In this article, I have provided the minimum amount of information so you can get started with logback quickly and easily. Remember that what I exposed mainly focuses on simple Java applications, but all concepts are general.
If you use complex frameworks like Helidon, Micronaut, Quarkus, etc., you should check the official documentation because logback may or may not be available by default.