Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure ELMAH with SignalR

Tags:

elmah

signalr

I'm using SignalR hub in my MVC4 application. I added ELMAH to handle all errors. the problem is that errors which happen in the Hub are not being logged in ELMAH axd. Is there a way to configure it?

like image 756
Haddar Macdasi Avatar asked Nov 27 '12 18:11

Haddar Macdasi


People also ask

How do you set up ELMAH?

To turn on ELMAH, navigate to Administration » Settings » Advanced » System » UI Elmah Config. Select the IsElmahLoggingTurnedOn checkbox and click Save changes.

Does ELMAH work with .NET core?

ELMAH doesn't support ASP.NET Core.

How do you check ELMAH?

Build the application, run it in the browser, and navigate to http://www.yoursite.com/elmah.axd. You are prompted to log in before you see the content. After a successful authentication, you see a web page to remotely view the entire log of recorded exceptions.


1 Answers

You have to add a HubPipelineModule, and also ensure you set an ApplicationName in your errorLog element, Otherwise Elmah won't be able to log an error, as it won't have an HttpContext, or an AppName to log to.

<errorLog type="Elmah.SqlErrorLog, Elmah" applicationName="MyAppName" connectionStringName="myConnString" />

The HubPipelineModule code I've used is as follows:

public class ElmahPipelineModule : HubPipelineModule
{
    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 void LogException(Exception e, IHubIncomingInvokerContext invokerContext)
    {
        var context = HttpContext.Current;
        ErrorLog el = ErrorLog.GetDefault(context);
        el.Log(new Error(e));
    }

    protected override void OnIncomingError(Exception ex, IHubIncomingInvokerContext context)
    {
        var exception = ex;
        if (ex is TargetInvocationException)
        {
            exception = ex.InnerException;
        }
        else if (ex is AggregateException)
        {
            exception = ex.InnerException;
        }

        if (!RaiseErrorSignal(exception))
            LogException(exception, context);
    }
}

Make sure you add the module to the hub pipeline:

GlobalHost.HubPipeline.AddModule(new ElmahPipelineModule()); 

EDIT

SignalR 2+

I noticed none of my SignalR exceptions were being logged in a recent project I've been working on, and have found that an ArgumentNullException is thrown when trying to get the ErrorSignal from current context. The following method properly deals with this exception so that SignalR errors are being logged once again.

private static bool RaiseErrorSignal(Exception e)
{
    var context = HttpContext.Current;
    if (context == null)
        return false;

    try
    {
        var signal = ErrorSignal.FromCurrentContext();
        if (signal == null)
            return false;
        signal.Raise(e, context);
        return true;
    }
    catch (ArgumentNullException)
    {
        return false;
    }
}
like image 138
damienc88 Avatar answered Sep 20 '22 07:09

damienc88