Let's take the following class struture as an example:
- SomeInterface
- AbstractImpl
private static final Logger logger = Logger.getLogger(AbstractImpl.class)
- ConcreteImpl_A
private static final Logger logger = Logger.getLogger(ConcreteImpl_A.class) - ConcreteImpl_B
private static final Logger logger = Logger.getLogger(ConcreteImpl_B.class)
- ConcreteImpl_A
- AbstractImpl
21 Apr 2011 DEBUG [main] (AbstractImpl.java:10) - the actual log message... which makes it difficult to distinguish between the concrete implementation classes that are actually being used when the message was logged.
21 Apr 2011 DEBUG [main] (AbstractImpl.java:10) - the actual log message
This entry helped me realize that the (AbstractImpl.java:10) portion of the logged line was being placed there by the regex (%F:%L) from the PatternLayout that was specified in the log4j.properties file like so:
log4j.appender.CONSOLE.layout.ConversionPattern=%d{dd MMM yyyy} %5p [%t] (%F:%L) - %m%nTherefore, the solution would be to add the regex [%c{1}]:
log4j.appender.CONSOLE.layout.ConversionPattern=%d{dd MMM yyyy} %5p [%t] [%c{1}] (%F:%L) - %m%nHoping to get logs that look like:
21 Apr 2011 DEBUG [main] [ConcreteImpl_A] (AbstractImpl.java:10) - the actual log message... but that will not happen yet because there is still one major flaw in the way the logger code in the java classes above has been written!
21 Apr 2011 DEBUG [main] [ConcreteImpl_B] (AbstractImpl.java:10) - the actual log message
The code needs to be like this:
- SomeInterface
- AbstractImpl
protected Logger logger = null;
- ConcreteImpl_A
private static final Logger myLogger = Logger.getLogger(ConcreteImpl_A.class)
public ConcreteImpl_A() {
super();
super.logger = myLogger;
} - ConcreteImpl_B
private static final Logger myLogger = Logger.getLogger(ConcreteImpl_B.class)
public ConcreteImpl_B() {
super();
super.logger = myLogger;
}
- ConcreteImpl_A
- AbstractImpl
Thanks for this post!
ReplyDeleteYou could also define the logger in the abstract class like so:
private final Logger log = Logger.getLogger(this.getClass());
This comment has been removed by the author.
ReplyDeleteNowhere in the constructor, you can garanty that this has been initialised ...
ReplyDeleteOnly once the constructor has been initialized you can be sure it has been fully initialised