Code & Iron

Making the Leap: Log4J to SLF4J

So. The team lead has come to you and said “time to switch project X over to SLF4J“. Or you’re the team lead and you just realized all your log statements only work with Log4J? What if that project dies out?

Freaking out? Worried you will have to manually edit lines upon lines of code? Time to hire a coop? Fear not brave coder. We will bring the full power of bulk editing and unix “diff” to bear on this one. (And a really experienced colleague of mine who helped me through this!)

For those who are unfamiliar, SLF4J is the Simple Logging Facade for Java. It is a layer on top of Log4J, Logback, and others that allows you to decouple your log statements from your underlying implementation. SLF4J is to Log4J as JPA is to Hibernate.

Also the interface it provides is absolutely delicious. No more checking isDebugEnabled() before a log statement to avoid performance hits, SLF4J does so automatically. Also, no more complex string concatenation inside logger.info(). In SLF4J the info, debug, error, trace, and fatal methods take objects and plug them into message placeholders “{}” for you, calling the toString() methods as appropriate.

So let’s switch your project over. First, check out a fresh working copy of the project you need to modify, let’s call it project-logging-dirty. Next, check out another working copy of the same project, in directory project-logging-clean.

Download the SLF4J Migrator Tool here:
It’s perfectly suited to changing from Log4J to SLF4J, but it has one problem: It touches every single line of every single.java file in your project, and screws up the whitespace more often that not. I personally hate losing svn/git history due to whitespace mods. I want to know who to svn blame (lol, bad joke) when I’m looking at this project in 6 months.

Run the SLF4J migrator against project-logging-dirty.


java -jar slf4j-migrator-1.6.4.jar

If you do an svn diff you will see a HUGE number of lines changed (which are mostly whitespace modifications). Let’s pull those changes by making a unified diff of the two directories, ignoring .svn and whitespace mods, and forward the output to a new file called slf4j.patch.


diff -udrEbBw -x.svn project-logging-dirty project-logging-clean > slf4j.patch

Change to project-logging-clean so that it’s your present working directory, and apply the patch!


patch -p1 -ZEBw --ignore-whitespace < ../slf4j.patch

Run svn diff again in project-logging-clean. You should see a clean changeover to SLF4J including LoggerFactory.getLogger statements and all the rest. Commit project-logging-clean once you've run all integration tests against the build. Delete project-logging-dirty, to never be seen again.

Caveat: When doing thread-specific concurrent programming, you may be using NDC (Nested Diagnostic Context), a stack of context specific log message parameters. NDC is unsafe as the log parameter stack could theoretically grow without bounds (memory leak anyone?). SLF4J does not support NDC, and switches to MDC (Map based, which is much more forgiving if you are writing to the log parameters forget to remove). Caution should be exercised when doing any thread specific logging: each map.put should have a corresponding map.remove, in a finally block. BUT take note: The SLF4J Migrator Tool cannot change over your NDC statements to MDC, you will need to do this manually.

Best of luck, I hope you have as much fun with SLF4J as I do!

  Posted by Matt Holtom in Blog, Programming on April 2, 2012  /  Tags: , , , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *