Exceptions are a great way to communicate error state back to the caller. The exception class basically defines the type of error, e.g.: AccessDenied that happened. The detailed message then explains the exact reason for the problem, e.g.: “Your user has no rights to access file xyz”.
Documentation of frameworks usually lists all types of exceptions that could potentially be thrown – allowing the caller to implement try-catch routines to handle those exceptions that make sense in order to implement program logic.
“The Good” thing about exceptions
The above described usage scenarios are a good thing about exceptions. Getting a detailed explanation in case a problem happened can make it easy for you to address the issue or even allows you to publish this error to the user interface. Using exceptions to control program logic is also a way to go (but still keep in mind the good old return values 🙂 )
“The Evil” thing about exceptions
In the past weeks I came across different scenarios where the above explained usage scenarios didn’t work. Here is why:
Scenario a) The Web Application returned a 403 Access Forbidden
The application used a 3rd party web control to display a questionnaire form. Some users of the web application could use it fine – others always got an UnauthorizedAccessException thrown by the Page_Load method of the 3rd party web control leading to a 403 HTTP Error. The exception had no detailed error message specified so it was impossible to find the exact root cause.
Using Dynatrace it was possible to find the root cause. It turned out that the web control accessed a local configuration file on the web server. Opening that file threw an AccessViolationException with a detailed error message that this user just had no access rights. The original message unfortunately was never thrown up to the application itself. Knowing the original exception helped to understand and address the problem.
Scenario b) The Application allowed restricted access to an unauthorized user
The application called into an authorization framework that would throw different kinds of exceptions in case the user did not have the appropriate access rights. The application would catch all different exceptions and implement different program logic to handle the situation.
In order to implement a logging facility, a new layer was introduced that was supposed to catch the exceptions thrown from the authorization framework, log the calls, and then rethrow the exception. Due to a bug in this layer, several exceptions indicating an authorization problem never made it to the actual caller. The application therefore continued the normal application flow as if the user would have had access.
Getting visibility into your application and all its frameworks it depends on enables you to better understand how to use your 3rd party frameworks. It also allows you to diagnose errors down to the root cause in case you don’t get the detailed explanation that you need.
The above image shows how Dynatrace tracks every exception that happens in your system. It also shows it in the context of a single transaction (PurePath) with all its contextual information, e.g: method parameters, …
Relying on frameworks is a mandatory thing these days. But not knowing what’s actually going on in those frameworks can lead to the above described side effects. With a solution like Dynatrace it is possible to analyze all exceptions that occurred within the application and not only within the custom application code.