7 Good Rules to Log Exceptions

I've been helping to debug some nasty problems and bugs lately. It occurred to me that some best practices on how to log exceptions go a long way towards easier debugging. Some of the best practices I've learned to log exceptions are compiled in this post.

1. Only log technical exceptions not user exceptions
User exceptions are either ok and need not to be logged ("login name already exists") but shown to the user, or no exception at all ("user has no credit left"). Technical exceptions are those you need to debug ("no file storage left", "could not book product") and react to. If you log everything you will probably get too many log entries to have a meaningful reaction to exceptions in your log. You should inquire into every exception in your log files and find the cause for it ("is it a bug?"). Too many exceptions will make you sloppy with exceptions in your log files ("nah, just another exception").

2. Store data in your exceptions to make them easier to log
Taking the exception "could not charge money from account" you should store the context of the exception just like Junit does ("expected but got ...") to make debugging easier

CannotChargeMoneyAccountException(Money moneyInAccount, Money toCharge, Account account)

The message could be: "Tried to charge 20 EUR from account 1234567890 but 10 EUR available" compared to "Charge failed". This makes it much easier later to log the exception in a meaningful way. Be careful to create no memory leaks though.

3. Log the description of your exception
Very bad example from Sun: The ClassCastException didn't show you what class you did want an object to cast to for a long time.

Now it even detects

final String s = "Hello";
final int x = (Integer) s;

and tells you

T.java:4: inconvertible types
found   : java.lang.String
required: java.lang.Integer
          final Integer x = (Integer) s;

During runtime the exception thrown by Java is now:

Exception in thread "main" java.lang.ClassCastException: 
java.lang.String cannot be cast to java.lang.Integer

Much better than before.

4. Output all causes to your exception
If your exception has an exception wrapped as a cause, log all causes. Some logging frameworks do this for you, some don't. Be sure to have all causes of your exception in the log file. Be sure the beginning of all relevant stack traces in your log, not scrambled ones.

5. Log to the right level
If your Exception is critical, log it as Level.CRITICAL. You need to decide what critical means for you (most often it means losing money). For example if a booking didn't work, or a user could not register due to technical problems then you have a CRITICAL problem you need to solve.

Monitor your log files for critical exceptions. You're losing money.

Have your own exception implement isCritical() or a CriticalException interface and test when logging the exception in your wrapper to log it on the right level. If your logging framework hasn't got an appropriate level, create one.

6. Don't log and rethrow
Logging and rethrowing an exception is an exception anti-pattern.

catch (NoUserException e) {
  LOG.error("No user available", e);
  throw new UserServiceException("No user available", e);

Don't do it. Your log files will then contain the same exceptions several times on several stack levels. Only log the exception once.

7. Do not log with System.out or System.err
Always use a log framework, it can handle logging better than you.

I hope those rule help you with your exception logging and enable you to easier debug your problems.

Thanks for listening. As ever, please do share your thoughts and additional tips in the comments below, or on your own blog (I have trackbacks enabled).

Update: For some Hackernews comments: Logging everything is fine but leads to ~50gig/day, 300gig/week, 1.2tb/month log files for a moderate site. Your grep won't work very good for that. Splunk will obviously help of course but is only free for 0.5gig/day, a 1/100 of the log files you will get.

Stephan Schmidt Administrator
CTO Coach , svese
Stephan is a CTO coach. He has been a coder since the early 80s, has founded several startups and worked in small and large companies as CTO. After he sold his latest startup he took up CTO coaching. He can be found on LinkedIn or follow him in Twitter.
follow me