Skip to main content

Simplifying logging with Maven and SLF4J

UPDATE:Ceki commented below which prompted me to rewrite the third paragraph.

UPDATE 2:I have a better way of configuring Maven and SLF4J now.

The mismatch between logging frameworks always seems to come up in projects I've developed over the years. Little-by-little I've learned and relearned how to navigate the nest of runtime logging that occurs in non-trivial applications. With my latest project I think I finally converged on a solution that I'll carry forward to future projects.

So what am I really talking about? Have you ever been stumped, even for a short time, about where a certain log message is going and why it might not appear in your log? Often this happens when you are trying to debug an issue with a third-party library that's using a different logging implementation them your application. If you are nodding from familiarity, skip the next paragraph.

Let's start from the beginning. There are several logging implementations available for Java, the best known being Log4J and the java.util.logging (JUL) API that was added in JDK 1.4. You may also encounter Apache commons-logging which is a logging facade for library developers to abstract their logging so library users are free to choose their own implementation such as Log4J. But commons-logging has well-documented issues so that's where slf4j comes in as my logging facade of choice. I actually code all my new applications to use the slf4j API directly because it adds functionality over the logging implementations like parameterized log messages that are only evaluated if the associated logging level is enabled. But that's tangent to this post.

So how have you solved the usage of multiple logging implementations? In the past I've tried different techniques:

  1. Configure each framework separately and have them write to their own log files.
    • Pro: Is there one?
    • Con: You need to monitor multiple files
    • Con: You need to understand the usage and configuration of each framework.
    • Con: If you are in a J2EE container you lose the log adminstration it provides.
  2. Redirect everyone to standard out and redirect standard out to a file.
    • Pro: Its all going one place.
    • Con: Its all in standard out, even errors which can make adminstration tools fail to filter messages properly.
    • Con: You still need to configure each secondary framework including message formatting so all log lines follow the same pattern.
  3. Write and connect bridges for each secondary framework so that they will log to one framework that is responsible for writing to the file, which I'll call the primary framework.
    • Pro: Its all going one place and category names, and levels are preserved through to the primary framework.
    • Pro: If the primary framework supports programmatic changes to log levels, it works for all frameworks.
    • Pro: If you are in a J2EE container that support live updating of log levels, it works for everything.
    • Con: You need to know what you are doing to develop the bridges, configure the bridge in each secondary framework and connect it all together properly.

So what's the magic solution I found? Well its a variation of #3 but it doesn't require any coding or any real knowledge of how to configure secondary frameworks. And I'll show you how to accomplish it using Maven and a logging facade API called SLF4J.

Here is the overview of the steps:
  1. Decide what the primary framework will be.
  2. Ban all secondary logging framework in your projects.
  3. Update your dependencies to exclude the banned dependencies.
  4. Configure your project to depend on drop-in replacements of each secondary logging framework from SLF4J and to use SLF4J to send everything to your primary framework.

Decide what the primary framework will be.

For my latest project, I'll be deploying to Glassfish which use JUL internally and has support in its admin console for live updating log levels without restarting the server, so it was easy to pick JUL as my primary framework.

Ban all secondary logging frameworks



Add the following plugin to your pom.xml


Add exclusions

This is where mvn dependency:tree -Dincludes=log4j:log4j is really helpful. If you try to build now, your build fail on the enforcer rule. Run this command to find which dependency is including log4j and add the necessary <exclusion>. Repeat until you find no more dependencies on log4j. Repeat for each of the banned dependencies.

Add dependency on SLF4J

Add the following to your pom.xml


Conclusion


So in 4 steps you can redirect all your logging to your primary logging framework without changing a line of code!

Comments

Ceki said…
Hi Brian,

Thank you for this article. I'd like to observe that apache commons-logging is not a logging implementation but a logging facade and only a logging facade.

Cheers,
Thanks Ceki, I updated the post to clarify that.
javin paul said…
Excellent article , you have indeed covered topic in details with code examples and explanation. I have also blogged some of my experience as 10 tips on logging in Java

Thanks
Javin
Yegor said…
Brian, you can also use http://www.jcabi.com/jcabi-maven-slf4j/, which does the same job, but without any coding. Just add a dependency to the project and use SLF4J as usual. I'm a developer of that binding.
Daniel said…
The SLF4J FAQ mentions three options for excluding other frameworks in Maven: SLF4J FAQ.

Interestingly IDEs, under default configuration, can add other logging framework jars onto the classpath; obscuring SLF4J.

Popular posts from this blog

3D Photo Viewer for Looking Glass

The Looking Glass I created my first Chrome extension, which is now live on the Chrome Web Store ! It's built for the Looking Glass , a holographic display that let's you view three-dimensional objects without glasses. I've also opened the source to the extension on GitHub. The Chrome extension allows you to view Facebook's "3D Photos", a feature they added in 2018 for displaying photos that include a depth map like those from phones with dual cameras, such as Apple's "Portrait Mode". Getting Started To use the extension, connect your Looking Glass to your computer, navigate to Facebook and open the viewer from the extension's popup menu. This will open a browser window on the Looking Glass display's screen in fullscreen mode. Opening the Viewer Once the viewer is open, the extension watches for any 3D Photo files being downloaded, so browse around Facebook looking for 3D Photos.  I recommend some of the Facebook groups de

My Journey to Fitness, a 5K, and my first Triathlon

At the finish line My name is Brian and Sunday I became a triathlete. My journey started ten months ago when I decided to get back into shape after 15 years of being obese and out-of-shape with some yo-yo dieting in the middle. What changed? I'll get to that. This weekend I competed in the first ever Rocketman Florida Triathlon which took place on the grounds of Kennedy Space Center at Cape Canaveral. In preparation I lost 50 lbs and 12 inches from my waist. But I'm getting ahead of myself. I'm a huge space buff. As a kid I wanted to become an astronaut. I went to Space Camp in Titusville when I was 10. Before that, I saw my first shuttle launch at 7 while on vacation. It was the final launch of the Challenger. I've written about that experience . I've seen three other launches since then including John Glenn's famous return to space as well as the final launch that ended the U.S. Shuttle Program. The idea of biking on the restricted grounds

Simplifying logging with Maven and SLF4J (Part 2)

So in my  previous post  I explained how to simplify your logging with Maven and SLF4J. If you haven't read it yet, please do before reading more.  Since then I've discovered an easier and cleaner way to remove the secondary frameworks from your Maven dependency tree. Here's a revised overview of the steps: Decided which logging framework will be your primary, aka who will actually write to your log file. Define the dependency scope of all the secondary frameworks to be ' provided '. Configure your project to depend on drop-in replacements of each secondary framework from SLF4J. Define secondary frameworks as provided Use the dependencyManagement section for this. Its used when you might have a dependency transitively. Add dependency on SLF4J Add the following to your pom.xml Conclusion So now in only 3 steps you can redirect all your logging to your primary logging framework without changing a line of code!