Logging is one of the most fundamental aspects of any language.
Unfortunately, Java’s in-built logging mechanism java.util.logging
(available since JDK 1.4) was not feature rich nor flexible enough for most use-cases.
The community created multiple libraries to fill in this gap.
After more than a decade, the logging ecosystem has become quite complicated with each library using its own logging mechanism. Even standard projects’ dependencies look like this.
and some conversations make no sense.
Let us try to understand how we got here.
If you are new to Java logging, refer to this article to understand its features.
Basics
log4j
was most used logging library in the beginning.
Once configured, using it in the code was relatively simple.
Facades
Though, using log4j
classes directly in the code results in tight coupling.
The solution to reduce this coupling was to introduce Simple Logging Facade for Java aka slf4j
;
a library which delegated the calls to the underlying logging implementation (eg: log4j
or logback
) based on runtime binding.
Bridges
Unfortunately, the community could not standardize on single facade to use.
Many Java libraries used different facades (eg: JCL
aka Jakarta Commons Logging) or in many cases direct implementations (ignoring the tight coupling problem).
This created a bigger problem.
Suppose you want to create a project and log with combination of slf4j
and logback
.
So far so good.
But what if you want to import a library say, Guava, and that in turn uses java.util.logging
How would your slf4j
or logback
know about that library’s logging mechanism?
Also, it is impractical to be aware of all libraries’ logging implementations and configure them separately in your project.
Thus, a bridge
(aka adaptor) was introduced, which would redirect all those logs called via java.util.logging
to slf4j
.
Problem solved. Now as long as you have the right bridge(s) for all the logging libraries
being used (directly and indirectly) in your project, all the logs will be flown/streamed
into slf4j
and into your final logging implementation.
slf4j
has all the bridges you will ever need.
The best part of this solution is – all the bridges are bound/configured automatically at runtime. Of course, the problem of which permutation-combination to use will still require including/excluding the right bridges/facades from your pom.xml. Though framework developers do think hard to make it easy for the developers.
Hit me up in the comments for any queries or critiques.