Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logging better exception information in Java

I am working on a largish Java web application with Spring, Hibernate, and some other libraries, including Apache log4j for logging. One of my ongoing projects is to rewrite a large number of exceptions in the legacy areas (which I didn't write!) of the code to give more sensible information. A typical exception block looks like this:

try {
  //Some Hibernate business here
}
catch (Exception e) {   //Yes, Exception. That's not just me being general. I find this especially frustrating.
  log4j.error("Fail to XXXXXX");   //again, real
  throw new MyException();
}

As you can guess, this makes for some challenging logs. I'm looking for a standard way to get better info out of these exceptions. Most of them wrap Hibernate calls, if that helps. Here's a typical block similar to one I just wrote:

try {
    myList.add( ((myClass) commonService.getRecordByTableId(myClass.class, ID)).toString() );
} catch (ServiceException e) {
    log4j.error("Failed to retrieve record from table myClass for id " + ID);
    e.printStackTrace();
}

Here I'm pulling a record from the database and adding it to a list. In the catch block I log what I think is a sensible message about what the try block is doing, and print a stack trace. So, my question: is there anything else I could/should be doing, in general, to get better information for diagnosing errors?

like image 389
andronikus Avatar asked Dec 01 '22 01:12

andronikus


2 Answers

In exceptions handling, Logging and re-throwing is a popular anti-pattern. You shouldn't do that. You need to decide between catching the exception, then properly handling it (including logging), or not catching it and allowing it to pass to higher levels (or rethrow it / wrap it in a runtime exception if it was a checked exception).

If you do that (log + rethrow), then there's no way for the upstream code to know that you've already logged the exception, and so the same exception might get logged twice or more, depending how many layers the exception has to go through, and what layer arbitrarily decide to log and re-throw it. That will make reading the logs and undestanding them a complete nightmare.

Also you could argue that throwing and catching exceptions are costly operations, all this catching and rethrowing isn't helping your performance at runtime.

So if you choose to actually handle the exception, then swallowing it is not the right way (even if you log some message). At the very least, you need to log the trace:

log4j.error("Failed to retrieve record from table myClass for id " + ID, e);
like image 145
Guillaume Avatar answered Dec 03 '22 14:12

Guillaume


printStackTrace() does not add the trace to your log. Supplying the exception to log4j will print it to your logfile where the context makes sense:

log4j.error("Failed to retrieve record from table myClass for id " + ID, e);
like image 29
rsp Avatar answered Dec 03 '22 15:12

rsp