Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to log chained exceptions?

I am a green developer trying to get a handle (har-har) on error handling in a large multi-layer java application. There are many situations where I believe that chaining exceptions through several layers is a good idea; e.g. when a failure in calling out to some external service at the lowest layer causes problems all the way up in the view:

  • Content X requested, but user isn't authorized
    • caused by: List of authorized users is null
      • caused by: User-management webservice responded Bad Request- Parameter foo must be formatted like 'xyz'

The most important exception, the one whose stacktrace I really want to examine, is the last in the chain; that I made a bad request and I need to fix foo's formatting. But when I let this exception bubble up through the layers, nicely chained in exceptions that are meaningful to each layer... when I eventually catch and log the thing, the default logging behavior always shows me gobs of detail about the outermost exception, and maybe 5 lines of stacktrace of the root cause.

This makes me want to log exceptions as they happen, AND let them bubble up, but then you end up logging most things twice; when they happen and when they are eventually caught.

What is the best practice here?

like image 352
PotataChipz Avatar asked Nov 08 '12 05:11

PotataChipz


2 Answers

I would recommend a different approach of exception management. At the top most layer of the application (like request entry point) create a try catch block to call any runtime exception. It's preferable that you have 2 catch blocks: - for your application specific (business) exceptions - for the rest (exception)

As you can see youl'l need to introduce you own exception type that you'll extend to create different exceptions for different purposes. For example you can create a custom exception for every layer of the application, for each integrarion etc. Use unchecked exeptions as they all will be handled on the top level. When any exceptional situation ocures (catch of low level exception) you should: - Put a description associated with the business context (for example "failed to load account data from DB" - Add description of the original exception (for example "Original error: Connection to DB failed") - Pass original exception to your exception in order to not loose the trace - Throw and forget. In other words top level catch block is responsible to handle it appropriatelly (rollback a transaction, show error message or anything else you may need

like image 198
Ruslan Platonov Avatar answered Nov 19 '22 22:11

Ruslan Platonov


Great question, I'm curious about other answers you will get.

I tend to take a "more is better" approach, and log at each step of the way. Does this make large logs? Yes, but when you're debugging an issue in a large Java application, you will be thankful for every log line you have. There are also tools (at the very least the grep, awk, sed trio) to help you filter through large files.

Another technique is to write this logging code, but turn it down (if you're using something like log4j, to the TRACE level). This way, should you run into an issue, you may not have the logs available, but it's a one line change (to lower the logging threshold) and you start generating a wealth of data for debugging.

In tandem with the previous technique, most logging libraries (again I'm falling back on my knowledge of log4j here) allow you to tune the log levels of different java packages. This means that you can write all of these "catch and rethrow" log lines as trace, and turn down the logging on lower level packages to WARN while you keep upper level packages at DEBUG or TRACE.

like image 1
Cory Kendall Avatar answered Nov 19 '22 23:11

Cory Kendall