Today I fell into an ugly Log4j logger trap. Everybody knows there is error, debug, info… method on Logger
object. But what you might not know is that there is no error(Throwable)
method there, only error(Object)
. What’s the difference, you ask? It’s quite big. There’s error(String, Throwable)
that will log out your message (the String param
), build Throwable
stack trace and log it along, but error(Object)
will treat exception just like every other object. There will be NO stack trace in your logs, only exception message, Throwable.toString()
will be called to generate it.
So there is only info that some NullPointerException
has occurred, but where it was thrown?
What you probably want do do in these situations is to call logger.error(ex.toString(), ex)
. This print exception message with stack trace included.
Try it for yourself:
import java.io.OutputStreamWriter;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;
public class TestClass {
private static final Logger logger = Logger.getLogger(TestClass.class);
public static void main(String[] args) {
ConsoleAppender consoleAppender = new ConsoleAppender(new SimpleLayout());
consoleAppender.setWriter(new OutputStreamWriter(System.out));
logger.addAppender(consoleAppender);
try {
doError();
} catch (Exception ex) {
logger.error(ex);
logger.error(ex.getLocalizedMessage(), ex);
}
}
private static void doError() {
new Object() {
void throwNpe() {
throw new NullPointerException();
}
}.throwNpe();
}
}
and compare the output of both logger.error
calls.
This made me quite mad today as I’ve really expected stack trace in my logs.
Filed under:
CodeProject,
Java,
Programming Tagged:
Java