Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to initialize slf4j (using log4j) logger properly in abstract classes / for inheritance

Tags:

slf4j

log4j

In my project I've got a top-level abstract class FrameProducer. I added a slf4j logger at this level, so that every inheriting class already has it. Here the code:

public abstract class FrameProducer extends Observable {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    protected BufferedImage frame;

    public BufferedImage getFrame() {
        return frame;
    }

    public void fireEvent() {
        logger.debug("Firing event. Implementing class: {}", this.getClass());
        setChanged();
        notifyObservers();
    }
}

There are also two inheriting classes: CameraFrameGrabber and GrayscaleFilter. Yet, when the method fireEvent() is being called from CameraFrameGrabber or GrayscaleFilter the message is being logged at FrameProducer level. Here the log, for clarity:

FrameProducer.fireEvent - Firing event. Implementing class: class com.ofj.frameaccess.CameraFrameGrabber
FrameProducer.fireEvent - Firing event. Implementing class: class com.ofj.frameaccess.GrayscaleFilter

Is it possible to initialize the logger in FrameProducer in a way that everything gets logged at the most-specialized level in my class hierarchy?

Thanks for any help.


Edit: My log4j.properties looks like this:

log4j.rootCategory=TRACE, CONSOLE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=DEBUG
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%C{1}.%M - %m%n
like image 499
mmm Avatar asked Oct 12 '10 11:10

mmm


2 Answers

Thanks for pointing out the right direction to look for possible corrections skaffman. I eventually changed my log4j.properties to (as one of the examples in the PatternLayout documentation says):

log4j.rootCategory=TRACE, CONSOLE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=DEBUG
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%-6r [%15.15t] %-5p %30.30c %x - %m%n

...and everything gets logged right.

like image 125
mmm Avatar answered Oct 18 '22 21:10

mmm


Logging in abstract classes is considered an anti-pattern by some because it introduces a potentially unexpected dependency. However if you are sure that all the stuff you are dealing with is your own that that's no problem I guess.

If you want to get the log message to show the concrete implementation rather than the abstract class name (which makes sense) then change your logging initialization statement in the abstract class to:

private final Logger logger = LoggerFactory.getLogger(getClass());

instead of something like:

private static final Logger logger = LoggerFactory.getLogger(MyAbstractClass.class);

i.e.

  • no static because it could be cast to something else.
  • getClass() instead of the specific class
like image 10
Mark D Avatar answered Oct 18 '22 22:10

Mark D