views:

61

answers:

2

I want to retrofit slf4j with Logback into a legacy application. Good thing is, the legacy application has its own logging framework. So all I had to do is alter the logging framework to log to slf4j instead of log4j.

It worked like a dream. I was happy, until I noticed the location Logback logged for each and every log event:

Logger.java:...

Yikes! That wasn't going to help my fellow developers much when trying to figure out where a log event came from.

How can I tell Logback to look a few levels up in the stack for the actual location to log?

The logger class is a utility class with methods like this:

public static void debug(String clazz, String message) {
    org.slf4j.Logger logger = LoggerFactory.getLogger(clazz);
    logger.debug(message);
}
+2  A: 

See the various XXX-over-slf4j implementations for how to do it.

Basically you want to replace your current logger framework completely. Not wrap slf4j.

Edit:

Another approach could be writing your own layout subclassing the one you use now, which has a revised meaning of the %m, %l etc fields which skips the extra stack frame.

Thorbjørn Ravn Andersen
I considered that solution, but currently there is no budget to replace 10000+ log statements scattered over 50+ projects.
Stijn Van Bael
You do not need to change the log statements, but the code it calls (which hopefully is in a library)
Thorbjørn Ravn Andersen
The logger framework has 10000+ method calls from all projects to it. So if I replaced the logger framework, wouldn't I have to replace all method calls to it as well?
Stijn Van Bael
If you replace the logger framework with another which behaves identically (provides the same interfaces, classes and methods) but instead behaves like one of the other emulator frameworks for slf4j it should give you the desired behaviour. Otherwise create your own layout - see updated answer.
Thorbjørn Ravn Andersen
+1  A: 

Found the solution looking at the source of jcl-over-slf4j. Most implementations of slf4j (including logback) use loggers that implement LocationAwareLogger, which has a log method that expects the fully qualified class name of the wrapping logger class as one of it's arguments:

private static final String FQCN = Logger.class.getName();


public static void debug(String clazz, String message) {
    org.slf4j.Logger logger = LoggerFactory.getLogger(clazz);
    if (logger instanceof LocationAwareLogger) {
        ((LocationAwareLogger) logger).log(null, FQCN, LocationAwareLogger.DEBUG_INT, message, null, null);
    } else {
        logger.debug(message);
    }
}
Stijn Van Bael