How to use ELMAH to manually log errors

Direct log writing method, working since ELMAH 1.0:

try 
{
    some code 
}
catch(Exception ex)
{
    Elmah.ErrorLog.GetDefault(HttpContext.Current).Log(new Elmah.Error(ex));
}

ELMAH 1.2 introduces a more flexible API:

try 
{
    some code 
}
catch(Exception ex)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}

There is a difference between the two solutions:

  • Raise method applies ELMAH filtering rules to the exception. Log method does not.
  • Raise is subscription based and is able to log one exception into the several loggers.

You can use the Elmah.ErrorSignal() method to log an issue without raising an exception.

try
{
    // Some code
}
catch(Exception ex)
{
    // Log error
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);

    // Continue
}

I'd recommend wrapping the call to Elmah in a simple wrapper class of your own.

using Elmah;

public static class ErrorLog
{
    /// <summary>
    /// Log error to Elmah
    /// </summary>
    public static void LogError(Exception ex, string contextualMessage=null)
    {
        try
        {
            // log error to Elmah
            if (contextualMessage != null) 
            {
                // log exception with contextual information that's visible when 
                // clicking on the error in the Elmah log
                var annotatedException = new Exception(contextualMessage, ex); 
                ErrorSignal.FromCurrentContext().Raise(annotatedException, HttpContext.Current);
            }
            else 
            {
                ErrorSignal.FromCurrentContext().Raise(ex, HttpContext.Current);
            }

            // send errors to ErrorWS (my own legacy service)
            // using (ErrorWSSoapClient client = new ErrorWSSoapClient())
            // {
            //    client.LogErrors(...);
            // }
        }
        catch (Exception)
        {
            // uh oh! just keep going
        }
    }
}

Then just call it whenever you need to log an error.

try {
   ...
} 
catch (Exception ex) 
{
    // log this and continue
    ErrorLog.LogError(ex, "Error sending email for order " + orderID);
}

This has the following benefits:

  • You don't need to remember this slightly archaic syntax of the Elmah call
  • If you have many DLLs you don't need to reference Elmah Core from every single one - and just put this in your own 'System' DLL.
  • If you ever need to do any special handling or just want to put in a breakpoint to debug errors you have it all one place.
  • If you ever move away from Elmah you can just change one place.
  • If you have legacy error logging you want to retain (I just happen to have a simple error logging mechanism that's tied into some UIs that I dont immediately have time to remove).

Note: I've added a 'contextualMessage' property for contextual information. You can omit this if you prefer but I find it very useful. Elmah automatically unwraps exceptions so the underlying exception will still be reported in the log but the contextualMessage will be visible when you click on it.