Logging exceptions without crufty code: a comparison of strategies
January 7th, 2009 Brian Gray, Consultant
You get in to work, grab a cup of coffee, and start your day with a nice, simple, easy-to-read method. Like this one:
public Long createUser(String username) {
User user = new User(username);
return userDao.create(user);
}
Then you think about debugging during development, production support, etc., and decide it would be best to get a stack trace on failure. So you refactor:
public Long createUser(String username) {
User user = new User(username);
try {
return userDao.create(user);
} catch (DatabaseException e) {
LOG.error("Error saving user with username " + username, e);
throw e;
}
}
The Problem
To start, your nice, easy-to-read method has become cruftier. More importantly, you now have more lines devoted to logging exceptions than you have for creating a user. And what if after you write the above method, Bob in the next cube writes another method in which he doesn’t remember to log the error, and Becky uses info level logging instead of debug?
The Solutions
In this post, I will describe four solutions that I have seen for solving this problem and describe some pros and cons for each. The four solutions are, in no particular order:
- Aspect-Oriented Programming (AOP): define an advice class that gets executed whenever any method throws an exception. Log the exception in the advice.
- The catch-all method (i.e. highest interface/tier logging): Log no exceptions at lower levels and allow all runtime exceptions to bubble up. At the highest tier (such as a web UI, main executable, Web Service, etc.), catch all exceptions and log them.
- Self-logging exceptions: Define a base exception class that logs itself in the constructor (takes a message and possibly a Class as parameters). All exceptions in the application must extend from this base class (3rd party or library exceptions must be caught and re-thrown), but no application code should ever log an exception.
- Developer logging: As above, each developer logs exceptions as they see fit.
How Do They Stack Up?
Here are what I (and a few other Summa consultants) consider the strengths and weaknesses of each approach:
| Pros | Cons | |
| AOP |
|
|
| The catch-all method |
|
|
| Self-logging exceptions |
|
|
| Developer logging |
|
|
So who wins? It depends. How large is the team? How much time do you have to set up a solution? How much experience do you have with similar approaches?
The real answer is that whatever you choose, some thought needs to go into your exception handling, and it should happen early. Otherwise, you default to the wild west, and changes to this approach halfway through your development cycle are not only expensive, but also lower the value of your final choice.
Entry Filed under: Software Development






2 Comments Add your own
1. Ben Northrop | January 7th, 2009 at 1:21 pm
Great post.
One additional disadvantage with AOP exception logging is the ability to add context to the logs. For example, if you wanted to log the state of some class data member when an exception occurred:
public class A {
public int x;
public void createUser(String username) {
try {
doSomething();
} catch(SomeException e) {
LOG.error("some exception when x = " + x, e);
}
}
}
AOP logging is sometimes “one size fits none”.
2. Brian Gray | January 7th, 2009 at 4:47 pm
That’s true. Catch all doesn’t really help with that (in fact, it’s the least informative of the methods), but the self-logging exceptions would allow you to pass in any info you’d like.
Leave a Comment
Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
Trackback this post | Subscribe to the comments via RSS Feed