In this post I would like to demonstrate how to minimize unhandled exceptions in your project and how to “handle” them by providing logging and reporting capabilities.

100% bug free code

I used to work for a company that had a slogan “100% BUG FREE CODE” (all slogans must be in caps or they are not taken seriously).

It turned out that “100% bug free code” was easily achievable using one of the following approaches.

  1. The application you are writing will never be released to actual users. As they say the only way to win is not to play.
  2. By using code like this:
          try 
          {
             //do something important, like
             SaveTheWorld();
          }
          catch
          {
              //do nothing.  The world is never saved, and no one knows why.
          }
    

    This one I have seen many times, sometimes in a scope of a single function, other times in scope of the whole application. In theory it solves the problem at hand very nicely. In reality it just sweeps exceptions under the rug and makes debugging, maintenance and customer support much much harder.

    If you know a developer who writes code like this, you are allowed to just walk over and punch (or spin kick) him in the liver. Then give him a look of “I pity the fool” and quickly run away before he recovers. You are only helping him to pay back for some of pain and suffering that he has and will cause.

  3. Using unit testing and believing that 100% code coverage is the same as “100% bug free code’. I used to go to the church of unit testing every sunday and after chanting “Unit tests will result in 100% bug free code” about a 100 times it really did feel like all my bugs were just a bad dream (It was a nightmare with an actual huge insect running after me). The only problem was that as much as I would like to think that I can put myself into actual end user shoes (I do have special orthopedic shoes for that), that is 100% impossible. As soon as your application launches, your customers will generate all kinds of exceptions, some real and some only in the minds of the customers, but mostly real.

There are other lesser known approaches, like whenever there is an exception just redirect a customer to the latest “cute chipmunk” video on youtube. When customer sees those cute chipmanks any memories of what they were doing will be quickly forgotten.

That works really great the first several times, but you have to be really careful because in no time customer may be sending you error reports that YouTube videos are freezing.

Bug vs Unhandled Exception

Unhandled exceptions are only a subset of all the bugs you will encounter. Let’s say there is an error in calculating Order Total, where you forget to add the tax at the end. This is not going to result in exception, but it still a bug since original business requirement was not implemented. This type of bug is much harder to track since you may have to rely on customer to notice the issue and then report it to you with a bonus of some colorful language. On the other hand when unhandled exception is triggered – there are ways to setup your application to log it or send it to you by email. In this way you can buy yourself a little bit of time by diverting customer to a very informative page:

An internal system error has occurred. Support has been notified and is looking into the issue. Would you like to play a game of chess while you wait for the resolution?

And while customer is taking a well deserved break playing chess, you can try to fix the exception or at least add it to your TODO list.

In this post we will only talk about bugs related to unhanded exception being thrown.

Minimizing Unhanded Exceptions

In a rare case that one of the approaches in ’100% bug free code’ section fails, here are some ways to minimize your unhandled exceptions.

Defensive programming

It may come as a total surprise to you, but writing good code will actually result in less bugs and unhanded exceptions. Please spread the word.

From Wikipedia: “defensive programming is a form of defensive design intended to ensure the continuing function of a piece of software in spite of unforeseeable usage of said software”. That should apply to any code that you write, unless your hobby is to spend your weekends fixing unhanded exceptions that should not have happened in the first place. There are plenty of articles written on the subject of defensive programming, so I will not go into too much details.

I would like to highlight a technique called Parameter Checking that will make your functions a lot less error-prone. Here is one example:

void JustAnotherFoo(string iAmNotNull, int iAmPositiveInteger)
{
    //Check that parameters are valid
    if (iAmNotNull == null)
          throw new ArgumentException("I have identity crisis", "iAmNotNull");
  
     if (iAmPositiveInteger <=1)
           throw new ArgumentException("I am having a bad day", "iAmPositiveInteger");
  
     //Do some stuff that will sometimes break if iAmNotNull is null
     ....

     //Do some other stuff that could break if iAmPositiveInteger is 
     //not what he says he is
     ...
}

With code like this, you will catch many of the previously unhandled exceptions before they get a chance to cause all kinds of unforeseen errors.

There are many approaches in C# to implementing parameter checking.

  • using fluent notation
    http://conditions.codeplex.com
  • with code contracts already included in CLR
    http://visualstudiomagazine.com/articles/2010/06/23/code-contracts.asp
  • using extension methods
    http://weblogs.asp.net/fredriknormen/archive/2008/05/08/how-to-validate-a-method-s-arguments.aspx
  • Unit testing

    As much as I like to harp on the idea that 100% code coverage can solve all life’s problems, including better night sleep, more satisfying sex life and even a better customer experience in some cases, writing unit tests can most certainly prevent many cases of unhanded exceptions. When a new exception is reported, it is a great practice to write a unit test to reproduce the exception (what in unit testing world is called red circle of doom). Then you fix the issue and make unit test pass (which in unit testing world is called green circle of awesome happiness).

    Automated testing

    This is more of UI testing using tools like selenium. This way you can automate common workflows in your application and run through them before each rollout. These types of tests run a lot slower then unit tests, but are much better at simulating actual end user experience. The approach where you write unit test to reproduce exception before fixing it, can also be used with Automated tests, in case unit tests are not sufficient to reproduce the issue.

    Manual QA

    In some cases it is very hard to automate a test or try to cover every possible edge case. Like double clicking on every shiny button on the screen, all at the same time. Basically what a normal end user does. In this case we need manual intervention, as in actual humans doing testing.

    For this scenario what you do is:

    1. Get a couple of QA people
    2. Train them that every time they find an unexpected exception they get a tasty biskit (something you can get in large volume from Costco)
    3. But if they don’t find any exceptions in certain period of time – you zap them with ever increasing wattage
    4. By the end of the week you will be out of Biskits and QA people

    The truth about Unhandled Exceptions

    You may want to seat down as it may come as a total shock to you,

    A program of any complexity is going to have unhandled exceptions.

    This is really important concept, so please to take your time to fully comprehend it. At first you may feel a little dizzy and nauseous, but unless your are pregnant, these symptoms may go away in a couple of minutes. In case you are pregnant though, try prune juice. I hear good things…

    You may repeat the phrase above several times. Maybe combine it with a bit of Buddhist chanting. Only when you have accepted the deep meaning in it and you are at peace with yourself, you are ready to proceed.

    Oh “Wise Exception Guru”, how should we deal with all these unhandled exceptions?

    There are several ways to deal with unhandled exceptions:

    1. Use a 3rd party tool, like ELMAH (worst or best name evar? you decide). These tools are usually easy to integrate with your projects. After integration, when exception occurs it will be handled by the 3rd party tool and will be stored in DB or another type of storage. Afterwards you can use UI provided by the 3rd party tool to browse the exceptions.
    2. Write your own custom implementation. Why? Because the gods of coding gave you a rare gift of writing the most readable, most maintainable and most testable code on this planet. Unfortunately it came with one of the biggest heads on the planet which makes it extremely difficult to get through the door. An alternative, but much less common reason is that you were looking for some of the features not offered by any of the 3rd party tools.
    3. Just change a name from “unhandled exceptions” to “user errors”. Whenever one of these “user errors” is reported, there is a scripted reply:

      You must have done something wrong.
      * If you are using windows, please reboot your computer at least 3 times.
      * If you are using IPhone, try pressing THE button or combination of THE button with turn off switch. That’s really all you can do.
      * If you are using Linux, use Emacs to modify config file to enable detailed logging. If that doesn’t present you with the error of your ways, your kernel may require recompiling.

    What do I want in my Exception Logging And Reporting Software (ELARS, because I can)?

    Before evaluating 3rd party solutions, I used a custom solution which worked like this:
    Anytime unhandled exception would occur it would trigger an email sent to a gmail account which was setup just for this purpose. Gmail is extremely nice tool for searching and filtering. It also has some shortcomings that I wanted to address by introducing 3rd party tool or writing a custom solution specifically for handling unhandled exceptions.

    Here is a list of features that are a MUST for exception handling software:

    • Integration with various project types
      At minimum it should support:

      • Web Project (ASP.NET, MVC)
      • Exe Project (Console, Windows Service)
      • Web Service (WCF)
    • Log context information at the time of exception
      To fix unhandled exception you must be able to reproduce it. Regular ASP.NET exception page usually includes just an error message and stack trace. Sometimes it is sufficient to reproduce the error, but most of the time we will require input from the end user, like what data they entered in the form, what is their username, what browser they used, etc…

      Instead, it is a lot more efficient for both developer and the end user, if for every unhandled exception, the application would automatically log all such information.

      For web application I would need:
      * Full Url and Query String
      * Session Variables
      * Request Form Items
      * Cookies

      For WCF service at a minimum we need to log RawData of the request being passed.

      There should also be an option to add custom fields to logged information. For example let’s say I store current CustomerID in session variable. Whenever I need to find out which customer triggered the exception, I need to run DB query to get customer name. Instead I could just add a custom field to Exception Log called “CustomerName” and run DB query at the time when exception is logged. Using this custom field can save you a lot of time.

    • UI to search exceptions
      When customer reports an unhanlded exception, the first thing I want to do is to find that exception in logs. As long as the context information related to exception is properly logged this task is pretty trivial, given that there is a flexible UI to list and find exceptions. I would like to be able to search by error message and any other context information mentioned in previous section.
    • Grouping similar exceptions
      Some exceptions may occur only once or twice a month, while others may be happening 1000s of times a day. To be able to prioritize the errors it is important to know how frequently they occur. When you start logging exceptions in ASP.NET you may find that you are quickly overwhelmed with large number of exceptions being logged. The solution in most cases is to stop using error log and go back to assuming that your system is working just fine and any end user reports to the contrary are just fabrications from communists. A better approach is to allow grouping unhandled exceptions by stack trace, error message, url and maybe some other fields specific to your system. This way instead of list of all error occurrences – you will get a list of unique errors and how many times they occurred.
    • Integration with bug tracking software
      Everyone knows that the first step to fixing unhandled exception or any bug is creating a new entry in a bug tracking software. This way, QA department will know what to test for the next rollout and your boss will know that you are spending most of your time fixing bugs from the last release instead of working on new features that were promised 2 months ago. It would be great to be able to link the “Error Group” from previous bullet point to a bug in Bug Tracking software, so that whenever bug actually gets resolved it can also be udpated Exception Logging software and then we can watch for it to make sure it never (ever ever ever) occurs again.
    • Reporting (nice to have)
      To intelligently judge the health of the application, reports should provide information like:
      * Number of errors per time period (like day, week, month, etc..). So you can see if your system is getting healthier over time or dying from untreated flu.
      * Regions (or namespaces) in your application where most exceptions occur. So that the developers with least exceptions can order developers with most exceptions to go get coffee, wash their car and maybe even walk the dog.

    What Exception Logging and Reporting software is currently available?

    • Elmah
      http://code.google.com/p/elmah
      - the grand daddy of them all. Supports only Web Projects out of the box.

    • Exceptioneer
      http://www.exceptioneer.com
      - Saas solution to error logging. Seems like a great fit for all the features I mentioned, except it seems like the company went out of business 2 years ago and all that is left is a zombie-site that is down half of the time. When the site is down the error message is “Internal exception has been handled by our Excepioneer”. Oh the Irony of it all.

    • CodeSmith Insight
      http://www.codesmithtools.com/product/insight
      - exception handling, reporting, bug tracking, customer communication and also makes coffee. But for a price. Plus it only makes regular coffee. Capuccino addon will cost you extra.

      WARNING: I would like to serve notice to CodeSmith marketing deapartment. I noticed that every blog post on the internet that talks about exception handling is usually followed by a comment from you about how your product is all that and makes coffee too. For ex. check out comments section here. This is spam and not the good type.

    • Enterprise Library Error Logger
      http://weblogs.asp.net/sukumarraju/archive/2009/10/04/microsoft-enterprise-library-4-1-exception-handling-block.aspx
      - built on top of logging block. Allows logging exceptions to event log, DB, email, etc.

      • Indepth evalutation for these tools

        This blog post is getting really long and majority of the people probably dosed off by this point. So I will leave it for another post.

        Conclusion

        In this article I talked about various approaches to handling unhanded exceptions.

        • If you are a developer you will come away empowered with knowledge that Unhanded exceptions can be handled.
        • If you are a pregnant woman you will learn of home remedies to use when you feel sick and nauseous
        • If you are a Unit test junky, you will add scathing comments to this article that will reinforce your beliefs

        Either way everyone will be happy.

        In the next article of this series, we will do a full review of various products available to help with logging and reporting unhandled exceptions.