如何使用ELMAH手动记录错误

Omu*_*Omu 257 c# error-logging elmah exception-handling

是否可以使用ELMAH执行以下操作?

logger.Log(" something");
Run Code Online (Sandbox Code Playgroud)

我正在做这样的事情:

try 
{
    // Code that might throw an exception 
}
catch(Exception ex)
{
    // I need to log error here...
}
Run Code Online (Sandbox Code Playgroud)

ELMAH不会自动记录此异常,因为它已被处理.

And*_*aev 410

直接日志写入方法,从ELMAH 1.0开始工作:

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

ELMAH 1.2引入了更灵活的API:

try 
{
    some code 
}
catch(Exception ex)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
Run Code Online (Sandbox Code Playgroud)

两种解决方案之间存在差异:

  • Raise方法将ELMAH过滤规则应用于异常.Log方法没有.
  • Raise 是基于订阅的,并且能够将一个例外记录到几个记录器中.

  • 我发现当POST返回包含Mvc4 .Net 4.5的不安全Html时,Elmah.ErrorSignal没有记录,在我的示例中,从带有SignInResponseMessage的Windows Access Control服务返回POST.Elmah.ErrorLog.GetDefault确实在那种情况下工作 (7认同)
  • 使用`Elmah.ErrorLog.Log()`时的一个重要警告:如果日志调用本身失败,它会抛出,可能会导致整个Web应用程序崩溃.`Raise()`无声地失败.例如:如果服务器端存在配置错误(例如,Elmah配置为将错误保存到磁盘,但没有正确访问logs文件夹),则会抛出`.Log()`方法.(这对于调试很有用,例如为什么不``.Raise()`记录任何东西?) (4认同)
  • 这些会记录Elmah中的错误,而不会导致应用程序停止工作.它允许您捕获常见异常,正确处理它们,但仍然能够记录它们. (3认同)

Sim*_*ver 90

我建议在一个你自己的简单包装类中包含对Elmah的调用.

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后只需在需要记录错误时调用它.

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

这有以下好处:

  • 你不需要记住Elmah调用的这种稍微过时的语法
  • 如果你有许多DLL,你不需要从每一个引用Elmah Core - 只需将它放在你自己的'系统'DLL中.
  • 如果您需要进行任何特殊处理,或者只是想放入一个断点来调试错误,那么您可以将它放在一个地方.
  • 如果你离开Elmah,你可以改变一个地方.
  • 如果你想要保留遗留错误日志记录(我碰巧有一个简单的错误记录机制,它绑定到一些我没有立即删除的UI).

注意:我为上下文信息添加了"contextualMessage"属性.如果您愿意,可以省略它,但我发现它非常有用.Elmah自动解包异常,因此仍然会在日志中报告基础异常,但是当您单击它时,contextualMessage将可见.

  • @JeremyCook我同意,但有一点需要注意,如果你不小心失败,错误处理程序往往最终会调用自己然后爆炸(哦,我实际上也在这里调用第三方API来记录错误).我可能不应该把这个留在这个答案中,但我曾经遇到过这样的事情发生过的糟糕经历 (3认同)
  • 我很喜欢用@ //哦哦吞下任何次要错误!继续前进.如果我的错误处理失败,我想知道.我希望它能产生一些噪音. (2认同)

big*_*gtv 29

您可以使用Elmah.ErrorSignal()方法记录问题而不会引发异常.

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

    // Continue
}
Run Code Online (Sandbox Code Playgroud)


Dar*_*rov 19

catch(Exception ex)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*ers 14

对的,这是可能的.ELMAH旨在拦截未处理的异常.但是,您可以通过ErrorSignal类向ELMAH发出异常信号.这些异常不会被抛出(不要冒泡),而只是发送给ELMAH(以及ErrorSignal类的Raise事件的订阅者).

一个小例子:

protected void ThrowExceptionAndSignalElmah()
{
    ErrorSignal.FromCurrentContext().Raise(new NotSupportedException());
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*hew 13

我希望在我开始从我的MVC4应用程序中排队邮件的线程中做同样的事情,因为当引发异常时我没有HttpContext可用.为此,我基于这个问题找到了以下内容,并在此处找到了另一个答案:elmah:没有HttpContext的异常?

在配置文件中,我指定了一个应用程序名称:

<elmah>
    <security allowRemoteAccess="false" />
    <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ELMAH" applicationName="myApplication"/>   
</elmah>
Run Code Online (Sandbox Code Playgroud)

然后在代码中(如上面提供的答案,但没有HttpContext),您可以传递null而不是HttpContext:

ThreadPool.QueueUserWorkItem(t => {
     try {
         ...
         mySmtpClient.Send(message);
     } catch (SomeException e) {
         Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(e));
     }
 });
Run Code Online (Sandbox Code Playgroud)


A. *_*rel 10

我在ASP.NET 核心上,我使用ElmahCore

使用 HttpContext(在控制器中)手动记录错误只需编写:

using ElmahCore;
...
HttpContext.RiseError(new Exception("Your Exception"));
Run Code Online (Sandbox Code Playgroud)

没有 HttpContext的应用程序的另一部分:

using ElmahCore;
...
ElmahExtensions.RiseError(new Exception("Your Exception"));
Run Code Online (Sandbox Code Playgroud)