Scott Hanselman

ELMAH: Error Logging Modules and Handlers for ASP.NET (and MVC too!)

April 23, '09 Comments [29] Posted in ASP.NET | ASP.NET MVC | Bugs | NerdDinner | Open Source
Sponsored By

Joe Lowrance said, er tweeted, it best when he said,

"the amount of attention ELMAH hasn't got is shocking."

ELMAH is one of those largely unknown and deeply awesome .NET Open Source projects that should be part of ASP.NET proper.

What is ELMAH?

I like to say that ELMAH is Tivo for your ASP.NET Errors. You can get your Yellow Screens of Death, with full call-stack back and analyze what's really happening. It's Exception Driven Development. What's it really do?

Once ELMAH has been dropped into a running web application and configured appropriately, you get the following facilites without changing a single line of your code:

  • Logging of nearly all unhandled exceptions.
  • A web page to remotely view the entire log of recoded exceptions.
  • A web page to remotely view the full details of any one logged exception.
  • In many cases, you can review the original yellow screen of death that ASP.NET generated for a given exception, even with customErrors mode turned off.
  • An e-mail notification of each error at the time it occurs.
  • An RSS feed of the last 15 errors from the log.
  • A number of backing storage implementations for the log, including in-memory, Microsoft SQL Server and several contributed by the community.

Created by Atif Aziz (@raboof on Twitter) and Scott Mitchell, ELMAH means is "Error Logging Modules and Handlers" and has been rocking my world since, well, September of 2004.

(Small Correction, Scott Mitchell helped writing the original MSDN article. ELMAH is 100% conceived of by Atif.)

From the project site:

ELMAH (Error Logging Modules and Handlers) is an application-wide error logging facility that is completely pluggable. It can be dynamically added to a running ASP.NET web application, or even all ASP.NET web applications on a machine, without any need for re-compilation or re-deployment.

ELMAH is wonderful for many reasons. First, because it just works. Second, because it's a fantastic example of effective use of HttpModules and HttpHandlers working together. Third, because it's been design with enough thought that nearly anything you'd want from it for use in a production site is there.

I'm sitting here in a cafe and I'm going to add ELMAH to the ASP.NET MVC-based NerdDinner.com Source Code. Actually, the site, as I don't need to recompile the source if I'm not doing anything tricky. ;)

Implementing ELMAH on your ASP.NET (MVC or otherwise) Site 

I download ELMAH, and I put its DLL in my /bin folder (or wherever you like to put libraries). ELMAH doesn't need to be referenced by your project directly if you don't want to. Ultimately it just needs to be in your bin folder so it can be found. You can put it in /lib and make a build event if you like, as long as it ends up in /bin.

Then I open up two instances of notepad and copy over a few HttpHandlers and HttpModules into my existing web.config. Tedious, but straightforward.

Where you put these depends on if you're using IIS6 or IIS7, but the general idea is the handlers looks like this:


....

....

and the modules looks like this:


...



...

You can pare it down a bit if you don't need ErrorMail, for example. Then, I hit my site at http://localhost:xxxx/elmah.axd and I get this Error log, similar to what you'd see via Trace.axd.

Error log for  on HANSELMAN-T60P (Page #1) - Windows Internet Explorer

Ok, no errors. Let's make some. I'll visit some messed up URLs and intentionally cause trouble...here's what ELMAH says now:

Error log for  on HANSELMAN-T60P (Page #1) - Windows Internet Explorer (2)

And I can drill down and see the Yellow Screen of Death (YSOD) as it "would have been."

Error System.ArgumentException [5] - Windows Internet Explorer

Now, this assumes my ASP.NET MVC site has no error handling to speak of. ELMAH is watching for unhandled exceptions and recording them, holding them in memory. I can also setup logs to SQL Server or VistaDB or SQLLite so they'll live beyond application recycles.

You can certainly secure access to the ELMAH pages. You can also pull the errors into your favorite RSS Reader, which is a killer feature, IMHO.

Making ELMAH work with ASP.NET MVC's "HandleError" Attribute

In ASP.NET MVC there's an attribute called [HandleError] that will grab anything that goes wrong inside your controllers and show the ~\Shared\Error.aspx View. However, because it "handles" the error, it hides it from ELMAH. Remember that [HandleError] is a declarative try/catch. In my case, I want to have ELMAH handle it.

There's two ways around this.

One, I made a method in my Controller like this:

public ActionResult Trouble()
{
return View("Error");
}

In my web.config, I have a customErrors section like this:



This sends folks to /Dinners/Trouble which shows the Error page, after ELMAH takes care of it.

Second, as an advanced technique, I could write my own derived HandleErrorWithELMAHAttribute that logs the error using ELMAH's API, then passes the exception up to the default handler with ASP.NET MVC.

Looks like Dan Swatik's blog is dead. :( UPDATE: Looks like Dan Swatik was coincidentally doing a similar thing error this morning! What's nice about the solution on Dan's Blog, is that it was written with the help of Atif Aziz himself! (Remember, Atif's The primary author of ELMAH!) Here's the StackOverflow question.

My naive solution is below, but Atif's is better as it signals the error to ELMAH's pipeline rather that logging directly as mine does. Here's the more correct version:

namespace MvcDemo
{
using System;
using System.Web;
using System.Web.Mvc;
using Elmah;

public class HandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute
{
public override void OnException(ExceptionContext context)
{
base.OnException(context);

var e = context.Exception;
if (!context.ExceptionHandled // if unhandled, will be logged anyhow
|| RaiseErrorSignal(e) // prefer signaling, if possible
|| IsFiltered(context)) // filtered?
return;

LogException(e);
}

private static bool RaiseErrorSignal(Exception e)
{
var context = HttpContext.Current;
if (context == null)
return false;
var signal = ErrorSignal.FromContext(context);
if (signal == null)
return false;
signal.Raise(e, context);
return true;
}

private static bool IsFiltered(ExceptionContext context)
{
var config = context.HttpContext.GetSection("elmah/errorFilter")
as ErrorFilterConfiguration;

if (config == null)
return false;

var testContext = new ErrorFilterModule.AssertionHelperContext(
context.Exception, HttpContext.Current);

return config.Assertion.Test(testContext);
}

private static void LogException(Exception e)
{
var context = HttpContext.Current;
ErrorLog.GetDefault(context).Log(new Error(e, context));
}
}
}

Below is my naive version.

I made this HandleErrorWithELMAHAttribute:

public class HandleErrorWithELMAHAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
try
{
var context = HttpContext.Current;
Error error = new Error(filterContext.Exception, context);
ErrorLog log = ErrorLog.GetDefault(context);
string id = log.Log(error);
}
catch (Exception localException)
{
//
// IMPORTANT! We swallow any exception raised during the
// logging and send them out to the trace . The idea
// here is that logging of exceptions by itself should not
// be critical to the overall operation of the application.
// The bad thing is that we catch ANY kind of exception,
// even system ones and potentially let them slip by.
//

Trace.WriteLine(localException);
}

base.OnException(filterContext);
}
}

Then I put the attribute on my ASP.NET MVC Controller like this:

[HandleErrorWithELMAHAttribute]
public class DinnersController : Controller {
...

Either way works, I actually kind of prefer the first one, although it requires a controller to have an essentially empty method to send folks to the shared error page. I keep the /Confused and /Trouble methods in there as I think it makes the site more personal.

Anyway, ELMAH rocks and you should use it today. Phil Haack loves ELMAH too! Jeff and the guys at StackOverflow use ELMAH also, albeit a "custom fork." (Release your code, Jeff!)

Time for me to to donate some money to the ELMAH Open Source efforts.

Related

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Friday, April 24, 2009 2:56:11 AM UTC
I was wondering if there is any way to limit number of kept/displayed errors. Something like log rotation. I've seen some neat filtering options.
Friday, April 24, 2009 3:39:45 AM UTC
ELMAH is a great addtion to any ASP.NET site. I forked a custom version of ELMAH when working on E.P.A. sites a few years ago. We then retro-fitted many existing ASP.NET sites with the new implementation. I still demo ELMAH when teaching error handling.

Friday, April 24, 2009 6:39:27 AM UTC
I started using ELMAH about an year ago. It's a great error logging tool. Although, we've moved away to the Microsoft Enterprise Library Exception Handling Component. I totally agree it should be part of ASP.net.
Friday, April 24, 2009 7:55:27 AM UTC
I love ELMAH. We use it in some of our applications at work. I remember using it first in early 2005. At that time there were some bugs with the SQL Server implementation that we had to fix to use it (but that is the power of open source).

You are right, it's sad that not enough of it is used.
Friday, April 24, 2009 3:10:29 PM UTC
Wow, you can even use Oracle as a backing store. I didn't know this thing existed.
RussellH
Friday, April 24, 2009 3:25:52 PM UTC
I love Elmah, it is the first thing I add when I start a new website or web app.
Friday, April 24, 2009 6:56:52 PM UTC
I've been using ELMAH for a few years and I don't know what I should have done without it. I've also extended it to log all session variables. Great stuff!
henningst
Friday, April 24, 2009 7:26:06 PM UTC
Fantastic, I was just wishing for something like this.
Jeff Sodeman
Friday, April 24, 2009 7:29:53 PM UTC
ELMAH is great, I've been using it on ASPAlliance.com since Scott and Atif's original MSDN article (forever ago). It's interesting you wrote about it just now, as I've seen it discussed in a few different places this past week, which triggered some renewed interest in getting an ASP.NET control panel built. I talked to you (and the team / SimonCal et al) at the MVP summit, too. I think it would be great if we had a central place to go in ASP.NET to view exceptions, trace output, cache data, etc. A lot of others agree (check out my post on it here: http://stevesmithblog.com/blog/asp-net-control-panel/ ), so I hope we see this at some future date.

Alternately, perhaps Atif would be interested in working on a project like this one. I'd be happy to help integrate the ASPAlliance CacheManager plugin (based on ELMAH's architecture already) into the resulting control panel plugin.
Friday, April 24, 2009 11:12:16 PM UTC
Do you think Microsoft would consider putting this into .NET 4.0 if it's not too late?

It's always good to stress exception handling (especially uncaught exceptions). That just seems like an afterthought for a lot of programmers:) Thanks for bringing it up.
Saturday, April 25, 2009 4:37:10 AM UTC
Scott, a small correction: I had no part in creating ELMAH or its codebase. That was Atif, 100%. My only contributions to the project have been coauthoring the article on MSDN you referenced and using ELMAH in all my projects and singing its praises to anyone who will listen. :-)
Saturday, April 25, 2009 12:37:04 PM UTC
Scott,

Thanks for this blog. ELMAh was never on my radar. I wasn't aware of this great tool.

Monday, April 27, 2009 12:59:41 AM UTC
Very Powerful!
Monday, April 27, 2009 4:06:17 AM UTC
Obviously this must work for most folks, but the download for ELMAH is a two-year-old beta.
Joe Reynolds
Tuesday, April 28, 2009 4:52:16 PM UTC
I've been using a modified version ELMAH for a couple years now and absolutely love it. We run alot of applications and preferred a single console where all monitored applications could be viewed/reported on rather than each having it's own instance at the site URL. It couldn't be any easier to get this up and running and has provided a proactive means of finding bugs and issues. as if... :)
rodnex
Thursday, April 30, 2009 2:37:04 AM UTC
There isn't a production web app I launch without it. I just haven't found a better way to catch and log unknown exceptions happening on the site. It's so easy to set up too.
Tuesday, May 05, 2009 2:31:51 AM UTC
Nice article. I will have to review this framework, but two questions that come to mind are:

1. Is this duplicate functionality of Log4Net and other logging frameworks?
2. How well does it perform? Compared to other frameworks?
Tuesday, May 05, 2009 9:10:43 AM UTC
Hi,

This caught my eye from an online article.

It seems I have to use the beta version as I'm using .NET 2008. Are you folks all using beta code? Just a bit suspicious of using beta code in applications I intend to deploy.

Andy
Andy Dray
Wednesday, May 06, 2009 7:57:18 AM UTC
And why does he not use the very powerful log4net component as the core log engine? Why build the wheel once again? It does not sound very open source-minded.;)
Martin Oddman
Wednesday, May 06, 2009 8:41:14 AM UTC
Martin and Paolo - ELMAH isn't simply logging, it's system-wide exception handling. It's instrumentation of not just exceptions but also HTTP Context. It compliments log4net, it doesn't replace it.
Wednesday, May 06, 2009 6:41:54 PM UTC
If you do not want to have open-source downloads, another good option is the build off of the asp.net health monitoring. A lot of options such as frequency for logging, intervals etc. can be configured in the machine web.config. And you can configure to use different data providers/Email as well.
Thursday, May 07, 2009 6:47:21 AM UTC
Hi Scott,

Thanks for the info. We will try to use this feature in our ASP.Net app's.

Is there anything for the Windows application ?

Thanks,
Thani
Thanigainathan.S
Wednesday, May 13, 2009 4:08:46 PM UTC
I got in the habit of working with self logging exceptions.
Classes that inherit from System.Exception and use the enterprise library’s logging block.
It works great and keeps me log worry free. All I have to do is make sure I throw one of my exceptions. The logging is written into the constructors. I wander what will perform better. EL or ELMAH.

public MyCustomException(string s, Exception innerException)
: base(s, innerException)
{
if (Logger.IsLoggingEnabled())
{
// Log exception
LogEntry entry = new LogEntry();
entry.Title = s;
entry.Message = innerException.Message;
if (innerException.InnerException != null)
entry.Message += Environment.NewLine + innerException.InnerException.Message;
if (Logger.ShouldLog(entry))
Logger.Write(entry);
}
}
Friday, May 15, 2009 7:18:46 PM UTC
Curious about why you like this more than the built-in health monitoring. According to this thread - http://markmail.org/message/xjlljkrtsnwyijha#query:health%20monitoring%20elmah+page:1+mid:xjlljkrtsnwyijha+state:results - there may not be a lot to gain from ELMAH in the current rev of ASP.NET? What do you think? I've tinkered with both, but not for a long time, so I'm trying to decide which path to take with a new project.
Monday, May 25, 2009 6:54:16 PM UTC
ELMAH works great, but I can't help being a bit annoyed by the fact that every extension is implemented as a HttpModule - as a way to piggyback on the instantiation procedures - when the things they do have little or nothing to do with the Http context. Then again, it works, so why bash it? :)
Sunday, May 31, 2009 1:02:41 AM UTC
I can't believe there is not a tutorial on how to get this to work with sql server for logging. I went here:
http://code.google.com/p/elmah/

and downloaded it and there is no information on how to get sql server to be used for the logging.

asdf
Monday, June 01, 2009 12:10:55 PM UTC
cool project, we have exception handling project too - http://www.codeplex.com/exceptionhandling :)
Wednesday, June 17, 2009 4:33:07 PM UTC
In response to the quote at the very top of the page, "the amount of attention ELMAH hasn't got is shocking." Perhaps I can shed some light. ELMAH suffers from horrible organization. The project itself, which lives on a Google page, looks like it was organized by a group of children, led by a 10 year old. There is no clear authoritative documentation, just a bunch of blogs scattered about. While ELMAH may be good for casual use, there are much better products on the market (SmartInspect is probably the best) for use professionally. So to me, what is really shocking, is that a bunch of intelligent grown men are able to create a supposedly great tool called ELMAH, but they can't do something simple like organize it and write a user manual. That's shocking!
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.