33

Is it possible to have a typical call to java.util.logging.Logger and have it route to Logback using SLF4J? This would be nice since I wouldn't have to refactor the old jul code line by line.

EG, say we have this line:

private static Logger logger = Logger.getLogger(MahClass.class.getName());
//...
logger.info("blah blah blah");

It would be nice to configure this to call through SLF4J.

try-catch-finally
  • 7,436
  • 6
  • 46
  • 67
Zombies
  • 25,039
  • 43
  • 140
  • 225
  • There is one major benefit by biting the bullet and refactor to slf4j. Namely that you can use {} in your strings to delay toString() calls. – Thorbjørn Ravn Andersen Jun 01 '11 at 09:06
  • Is toString() really a concern with modern JVMs? I realize it is more efficient to avoid toString() calls, but my understanding is that object creation is cheap and that this would fall under premature optimization. – Michael Easter May 30 '12 at 11:16
  • yes it is really is a concern if you are making rich logging statements. profiling a production system in 2015 on a modern jvm unnecessary calls to create strings for debug statements that are not actual enabled in production is a cpu hotspot for the production system. – simbo1905 Nov 28 '15 at 11:52
  • Yes, it is possible. And it is very easy, you don't have to change any source code. You only must change some .jar libraries. Look at this articles - [logging-with-slf4j](http://www.baptiste-wicht.com/2010/02/logging-with-slf4j/) - [legacy logging](http://www.slf4j.org/legacy.html) - [SLF4J logging](http://blog.espenberntsen.net/tag/logback/) – user179437 May 16 '11 at 17:19

1 Answers1

58

It's very easy and not a performance issue anymore.

There are two ways documented in the SLF4J manual. There are also precise examples in the Javadocs

Add jul-to-slf4j.jar to your classpath. Or through maven dependency:

<dependency>
    <groupId>org.slf4j</groupId>
     <artifactId>jul-to-slf4j</artifactId>
    <version>1.7.0</version>
</dependency>

If you don't have logging.properties (for java.util.logging), add this to your bootstrap code:

SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();

If you have logging.properties (and want to keep it), add this to it:

handlers = org.slf4j.bridge.SLF4JBridgeHandler

In order to avoid performance penalty, add this contextListener to logback.xml (as of logback version 0.9.25):

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
        <!-- reset all previous level configurations of all j.u.l. loggers -->
        <resetJUL>true</resetJUL>
    </contextListener> 

    ...

</configuration>
Charlie
  • 8,530
  • 2
  • 55
  • 53
Dejan Milosevic
  • 1,092
  • 1
  • 11
  • 12
  • Just a note - I had to reload Logback configuration to make this working for me. – Bartosz Firyn Mar 27 '14 at 16:23
  • 1
    Adding the contextListener configuration was necessary anyway to propagate the logback configuration to the jul logger. So regardless of the performance improvement it was necessary for us. – bric3 Oct 13 '16 at 15:55
  • It may be related to that bug in some way : http://jira.qos.ch/browse/LOGBACK-404 i.e. without the propagator Logger are not kept and then their level reset. – bric3 Oct 13 '16 at 16:06
  • `add this to your bootstrap code` spring's bootstrap-code is not used in war-archive for deployment. – Grim Jun 19 '23 at 07:11