Error Handling with ELMAH in ASP.NET MVC

Every major software project, across the board has one crosscutting concern that they have to take care of – Error Logging and Management. Over the years, various frameworks have matured into robust error logging frameworks like Log4Net, Microsoft Exception Handling framework, NLog etc. While logging frameworks focus on handling errors and other application flow/state information, logging them appropriately at all layers, today we will look at EMLAH a framework that tackles errors that fell through the cracks aka Unhandled errors. It is written by Atif Aziz and serves as an excellent tool for managing and viewing Unhandled/Unexpected exception scenarios.

ELMAH stands for Error Logging Modules and Handlers. Over the past years, it has matured extremely well and in its current Nuget Package distribution mode, it is simply a zero configuration drop in for basic functionality. So let’s get started with the basic functionality and then go back to see what the initial configuration is and what it implies.

We will use our FunWithSignalR project and add ELMAH to it.

Installation and Basic Functionality

1. It’s a single step installation in the Nuget package management console command

install-package elmah

2. After installation, to test ELMAH we update the BlogPost\Index.cshtml with an incorrect View Name for the ‘Create New’ action.

update-index-error

3. Now we run our application.

4. Click on the ‘Create’ link and instead of the expected Yellow Screen of death, you briefly see a warning that flashes and goes away. Nice, where did that come from? ELMAH!

injected-error-message

5. Now let’s open the elmah.axd (in the current case at the URL http://localhost:1475/elmah.axd)

elmah-report-home

a. As we can see, it caught and logged the error ‘A public action method ‘Create1’ was not found on the controller….’ When we click on the ‘Details…’ of the exception, we get a boat load of related information as shown below

The stack trace –

error-exception

The server variables –

elmah-report-details-2

As we can see, a load of data is recorded per exception.

6. Discovering Hidden issues: In the screenshot, we caused on exception by providing the name of the Controller Action incorrectly however we can see two additional errors, the details of which tell us that there are some images that are missing and could potentially cause missing images or placeholders for particular images. This helps us pro-actively track down issues in our web applications.

7. The log is in memory by default. If you scroll to the bottom of the error page we will see that the log is currently in-memory so blowing away the server instance will result in losing the log

elmah-report-memory-based

 

The Default Configuration Dissected

Now that we have see what the basic ELMAH configuration works like, lets look at the configuration that came out of the box. We will do a ‘diff’ of the web.config before and after ELMAH installation using Nuget. From top to bottom the changes in the web.config are as follows

1. ELMAH sections added to web.config

elmah-config-changes-sectionGroups

ELMAH adds a section group called ‘elmah’ that has 4 subsections – security, errorLog, errorMail, errorFilter.

2. Additional Dependencies added: ELMAH uses Newtonsoft.Json a open-source JSON library

elmah-config-dependencies

3. HTTP Modules installed. We see by default the Logging Module (ErrorLogModule, the emailing module and the Error Filter Module)

elmah-config-httpmodules

4. ManagedModules Installed. As seen below, the three most important modules for ELMAH are installed by default – In-memory Logging using the ErrorLogModule, Emailing errors using the ErrorMailModule and Filtering Errors in configured using the ErrorFilterModule.

elmah-config-managed-modules

5. Configuration Details

elmah-config-details

  • a. Location Path is the URL where the ELMAH dashboard is available, inheritedInChildApplications=”false” implies that child applications will not be monitored by ELMAH.
  • b. Verbs on which handlers should be applied.
  • c. By default Authorization is disabled, as is remote access. If you enable remote access, it is IMPORTANT that you setup Authorization properly. Only administrators should have access to ELMAH logs in production.

Setting up ELMAH to filter exceptions

As we saw above, ELMAH logs every unhandled exception that occurs in the system. However we may want to tone this down a little by asking it to ignore certain types of exceptions. ELMAH can be configured to do so by adding the filters in the <elmah> section of the web.config. For example if we wanted to ignore HTTP 404 exceptions, we could setup the ELMAH section as follows:

<elmah>
<errorFilter>
  <test>
   <equal binding="HttpStatusCode" value="404" type="Int32" />
  </test>
</errorFilter>
</elmah>

Once we set the above filter up and restart our server, we will no longer get the previous error reported.

elmah-filtered-404-via-configuration

Finer grained control over Error filtering Programmatically

As we see, filtering via configuration is convenient but may miss important errors. We can gain finer control over filtering by adding ELMAH event handlers in the Global.asax.

For example, in our case we want to ignore the 404 errors caused by missing images, but we do want to know if anywhere we are referring to wrong actions. We can do so by the following:

1. Trap the ErrorLog_Filtering exception in Global.asax

2. Check for condition and dismiss it if required. In our case, if we remove the above configuration, we get a ‘File does not exist’ error for each missing image. Let’s assume we don’t want to see this error in our logs but we do want to see Exceptions due to calls to incorrect Actions. How can we do this because both raise HttpException with status code 404. One hack is shown below:

void ErrorLog_Filtering(object sender, ExceptionFilterEventArgs e)
{
      if (e.Exception.Message.StartsWith(@"File does not exist"))
                e.Dismiss();
}

This code when placed in the Global.asax will ignore the ‘File does not exist’ error but will log the Action missing exception as we see below:

elmah-report-home

Filtering via exception message may not be a model solution, but we get an idea of how we can Filter exceptions that are trapped by ELMAH.

Using ELMAH to log Errors Programmatically

Though ELMAH is typically used as a drop in to oversee unhandled exceptions, it could also be used for logging exceptions in your web tier. A typical scenario would be a cross-functional transaction exception. For example, a user is registering on a site and on successful completion, the site sends out a confirmation email. You could consider saving registration data + sending mail to be a transaction and roll back a successful registration save if email sending fails, but is that a good UX? Probably not! No one likes filling registration pages, much less filling it out twice for some error on server side. So instead of rolling back the transaction we could simple log the error and send it over to ELMAH.

Code to do this is as follows:

// Try to send the confirmation e-mail
try
{
  // ...
}
catch (Exception e)
{
  // Log it via ELMAH
  ErrorSignal.FromCurrentContext().Raise(e);
}

Setting Up ELMAH to save logs to SQL Server

Now as we saw earlier, ELMAH by default is setup to save logs in-memory. It however supports a plethora of backend persistence stores for the logs. One of them is SQL Server. To setup SQL Server we need to do the following

1. Get the appropriate DDL script from http://code.google.com/p/elmah/wiki/Downloads?tm=2

2. Execute the script in your Application Database. This adds a new Table ‘ELMAH_error’ to your database

elmah-sql-log-table

3. Now setup SQLServer logger as follows

elmah-sql-config-string

Update the connection string with your connection string to the database you are using.

4. Generate the error and navigate to the ELMAH page to verify the Log location.

elmah-sql-server-log-message

5. You can double check on the server by querying through management studio.

elmah-query-sql-databse

ELMAH and Log4Net

A common question on forums is should I use ELMAH or Log4Net. Fact is ELMAH and Log4Net are not mutually exclusive rather a complimentary suite of tools. You should use both.

Use Log4Net to log known and perceived error conditions or Debug and Info messages to know more about application exception, usage and flow.

Use ELMAH at the Web layer to ensure unexpected/unhandled error conditions are managed by it and user gets a better UX in such exception cases instead of the Yellow Screen of Death (YSoD). Of course feel free to replace Log4Net with your favorite logging mechanism if you want.

Conclusion

ELMAH is a pretty powerful and configurable set of Handlers and Modules to manage unhandled web exceptions. Use it to keep a close eye on error and exception conditions in a web application.

References

Article by Scott Mitchell and Atif

Article by Scott Hanselman

ELMAH Wiki






5 comments:

Samuel Stanley said...

I am very pleased to find this blog. I want to thank for your time for this wonderful read!!! Keep Sharing, I'll surely be looking for more.

Steve Kumbsky said...

In step 4, you state "instead of the expected Yellow Screen of death, you briefly see a warning that flashes and goes away. Nice, where did that come from? ELMAH!"

Based on a blog response I got from Atif Aziz (creator of ELMAH), ELMAH does not provide any overrides to displayed error pages. Can you please clarify how you display the warning? Looks like a jQuery popup.

Brett J said...

I would also like to see Steve's Question answered. I would love a JQuery Alert box when an error occurs instead of redirecting to a error page.

Unknown said...

Who can see the elmah.axd page? Would a user be able to see all that information if they know about the elmah.axd page (for instance a hacker)?

Nabil said...

this is awesome article you posted. i've implemented this everything is working fine.

can you add more to this ?
how can we add more columns in grid. like StatusCode and User. if we want to show more columns like IP Address, UserID etc ?