Java logging libraries explained
When looking at the various Java-based logging libraries, it’s hard to see the forest through the trees. SLF4j, Log4j, Logback, what’s the difference? What’s this strange log4j-slf4j-impl library doing in my stack? And why does this library keep logging in Log4j format while I’ve configured Logback? You can find answers to all these questions in this guide. Note that I won’t cover all logging libraries, but just the most common ones.
Log4j is the oldest logging stack of them all. It comes in a set of two dependencies, one being the interface and the other being the implementation. You can use this logging stack of two dependencies standalone in your application. Your code uses the Log4j API and the Log4j-core library does the work.
SLF4J & Logback
What is the difference between SLF4J and Logback/Log4j?
The original author of Log4j 1.x (latest version is 2.x) created a successor which became Logback, a new logging library implementation. SLF4J (Simple Logging Facade for Java) on the other hand, is purely an interface/API, which is implemented by Logback. Your code uses the SLF4J API and the Logback library does the work. If you only include the slf4j-api dependency in your project, without an implementation such as Logback, all your log calls will end up nowhere (no-op).
This stack is perfect when you don’t use libraries with a dependency on Log4j. However, if you do, then I recommend using the
Log4j to SLF4Jstack mentioned later in this article. It also uses SLF4j as the API and Logback as the implementation, but it also makes sure that the Log4j-based logs of your libraries also end up going through your SLF4j-Logback stack.
SLF4J to Log4j
Can we use Log4j and SLF4J together?
Yes, you can, which brings us to another logging stack, which is a combination of SLF4J as the API and Log4j as the implementation. To achieve this, you need to use the
log4j-slf4j-impl library, which provides a bridge between the SLF4J API and the Log4j 2 API. Your code will use the SLF4J API and the log4j-core dependency provides the logging implementation.
Log4j to SLF4J
The inverse of the previous stack. The
log4j-over-slf4j binding library captures all Log4j calls and routes them to the SLF4J API. It’s primarily a stack to migrate applications coded against the Log4J API to the SLF4J API and then use a different logging implementation, such as Logback.
Help: I’ve configured this stack, but it keeps logging with log4j instead of using my new Logback configuration!
When using this stack, it is important to remove the Log4j dependency from your project and also exclude it from any other library dependency that is trying to pull it in. Otherwise, the remaining Log4j library will take over and your logs won’t be routed to the SLF4J API.
In December 2021, a major Log4j vulnerability in all versions prior to or equal version 2.14 shook the world of JVM-based app deployments. Luckily, the Log4j team patched this vulnerability quickly, but every project using this old version still had to apply the newest version. One alternative option for application maintainers, instead of upgrading to the newest Log4j library, could’ve been to apply this log4j-over-slf4j stack, which essentially removes the Log4j dependency altogether.
One last word of caution when using this logging stack is that you should never combine the log4j-over-slf4j library with the log4j-slf4j-impl library, as it will cause a loop, causing your logs to end up nowhere.