Trace Listener for Elmah (ASP / MVC Exception Logger)

Elmah is an awesome tool, you can make it LOG most of your exceptions for your ASP.NET app just by installing the NUGET package. (with a little work you can change most to all)

Install-Package elmah

Once you have it installed any exception that is not handled will be logged by elmah and will show in the exception web interface. Just navigate to <yoursite>/elmah./elmah.axd and you will see your errors.

If you have ever used log4net you will probably found its trace listener very usefull, you just need code like

 
Diagnostics.Trace.TraceInformation(&amp;quot;Hello, this is some INFO&amp;quot;);

 

And this will make its way to your log4net log. To be honest, I allays use Trace and then if I use the code in a console I use a console trace listener and if I run the code from MSTEST logs end up in MSTEST. At any point I can just plug in a log4net listener in and change the logging destination. For me that just feels right.

I could not find a TraceListener for Elmah so, I thought I would code one up.

Firstly, Elmah logging requires an Exception Class and this class name is used in the log. So, a typical log looks like

log display showing category as class name

In order to show a type that indicates the log type eg, Warning,Information or Error we create a class to represent each of these :

 
internal class TraceInformation : Exception
{
  internal TraceInformation(string message) : base(message){}
}
internal class TraceError: Exception
{
  internal TraceError(string message) : base(message) { }
}
internal class TraceWarning : Exception
{
  internal TraceWarning(string message) : base(message) { }
}
internal class TraceWrite : Exception
{
  internal TraceWrite(string message) : base(message) { }
} 

As you can see, we also have a Write class, this is for simple Trace.Writes.

Now we need to create a Listener, this is simple and the code looks like this

    internal class ElmahListener : System.Diagnostics.TraceListener
    {
        public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args)
        {
            TraceEvent(eventCache, source, eventType, id, string.Format(format, args));
        }
        public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message) //
        {
            Exception exception;
            switch (eventType)
            {
                case TraceEventType.Information:
                    exception = new TraceInformation(message);
                    break;
                case TraceEventType.Error:
                    exception = new TraceError(message);
                    break;
                case TraceEventType.Warning:
                    exception = new TraceWarning(message);
                    break;
                default:
                    exception = new TraceWrite(message);
                    break;
            }
            if (HttpContext.Current.Session == null)
            {
                ErrorLog.GetDefault(null).Log(new Error(exception));
            }
            else
            {
                ErrorSignal.FromCurrentContext().Raise(exception );
            }
        }
        public override void TraceTransfer(TraceEventCache eventCache, string source, int id, string message, Guid relatedActivityId)
        {
            base.TraceTransfer(eventCache, source, id, message, relatedActivityId);
        }
        public override void Write(string message)
        {
        }
        public override void WriteLine(string message)
        {
        }
    }

As mentioed earlyer, we need to create an exception to hold our message as this is just how Elmah works. You need to pass it an exception and it uses the TypeName for the Type column in the website. If we just used exception then the type logged would be exception for all our Trace Logs.

As we are not throwing or catching these exception we don’t take any performance hit, we are just creating them to hold the trace message and type.

You will notice that we check HttpContext.Current.Session , this will be NULL if we have no request object on the context, we sometimes have a context but no request for example in the Application_Start we have Context but no Request and that will cause Elmah to error.

An example of some this in action.

LogExample

Sourcecode https://github.com/TrueNorthIT/Elmah/tree/master/TrueNorth.Elmah

2 thoughts on “Trace Listener for Elmah (ASP / MVC Exception Logger)

  1. That’s a nice way to integrate trace listener with ELMAH. Have you considered creating this in a library on GitHub or similar? I think a lot of people using ELMAH and trace would benefit from your code.

    BTW I think you have a typo in the code. You reference /elmah./elmah.axd, but it should really be /elmah.axd, right?

    1. We were going it put it on git but I thought it was to small. I will put it on git later today and correct the typo. Thanks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s