Watch out for bad logging: Apache Commons Logging

If you (or your team) use Apache Commons Logging as a logging framework, you may encounter an incorrect way how you log your exceptions (regardless of the logging level – WARN, ERROR, …). It looks like this:

try {
  ... some code ...
} catch (Exception e) {
  log.error(e);
}

// or

try { 
  ... some code ...
} catch (Exception e) {
  log.error("Unexpected exception: " + e);
}

Logging with one parameter has this method signature:

Main purpose of this method is to log a message not a stack trace. So, if you catch and Exception object and pass it as a parameter then it just calls toString() on it. According to JavaDoc for Exception class toString() method returns a short description of that throwable.

Same when you use log.error(“An error occurred:” + e). You just combining two strings: “An error occurred:” plus e.toString(). Therefore, you don’t log the stack trace. In most cases it will only tell you that an error occurred (with short description), but you won’t know where. With exception like FileNotFoundException this can still guide you because its short description mostly contains the path to the file that was not found. But for more complex errors it doesn’t tell you much. Stack trace is swallowed and lost.

The right way is to use this method signature with two parameters:

You pass information message as a first parameter and Exception object as a second:

try {
   ... some code ...
} catch (Exception e) {
   log.error ("An error occurred", e);
}

Finally, let’s look at what information individual logging methods provide us:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class LoggingExample {

    private static Log log = LogFactory.getLog(LoggingExample.class);

    public static void main(String[] args) {
        try {
            int i = 5 / 0;
        } catch (Exception e) {
            // BAD APPROACH 1
            log.error(e);
            // BAD APPROACH 2
            log.error("Unexpected exception: " + e);
            // GOOD APPROACH
            log.error("Unexpected exception", e);
        }
    }

}

Log looks like this:

//BAD APPROACH 1. I don't know where the error occurred
SEVERE: java.lang.ArithmeticException: / by zero

// BAD APPROACH 2. I don't know where the error occurred
SEVERE: Unexpected exception: java.lang.ArithmeticException: / by zero

// GOOD APPROACH
SEVERE: Unexpected exception
java.lang.ArithmeticException: / by zero
    at LoggingExample.main(LoggingExample.java:10)

As you can see the third approach (good one) log the message and the whole stack trace. In addition, you don’t have to put any colon or space: Apache Commons Logging will format it itself.

Good luck with your logs!

Leave a Reply

Your email address will not be published. Required fields are marked *