如何使用ELMAH手动记录错误

时间:2011-09-16 06:42:57

标签: c# exception-handling elmah error-logging

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

logger.Log(" something");

我正在做这样的事情:

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

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

10 个答案:

答案 0 :(得分:405)

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

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

ELMAH 1.2引入了更灵活的API:

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

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

  • Raise方法将ELMAH过滤规则应用于异常。 Log方法没有。
  • Raise是基于订阅的,可以将一个例外记录到多个记录器中。

答案 1 :(得分: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
        }
    }
}

然后只要您需要记录错误就调用它。

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

这有以下好处:

  • 你不需要记住Elmah召唤的这种略显陈旧的语法
  • 如果你有很多DLL,你不需要从每一个引用Elmah Core - 只需将它放在你自己的'系统'DLL中。
  • 如果您需要进行任何特殊处理,或者只想放入一个断点来调试错误,那么您可以将它放在一个地方。
  • 如果你离开Elmah,你可以改变一个地方。
  • 如果你想要保留遗留错误记录(我恰好有一个简单的错误记录机制,它与一些我没有立即删除的UI相关联。)

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

答案 2 :(得分:29)

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

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

    // Continue
}

答案 3 :(得分:19)

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

答案 4 :(得分:14)

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

一个小例子:

protected void ThrowExceptionAndSignalElmah()
{
    ErrorSignal.FromCurrentContext().Raise(new NotSupportedException());
}

答案 5 :(得分:13)

我希望在我开始在我的MVC4应用程序中对邮件进行排队的线程中执行相同的操作,因此在引发异常时我没有HttpContext可用。为此,我根据这个问题找到了以下内容,并在此处找到了另一个答案:elmah: exceptions without HttpContext?

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

<elmah>
    <security allowRemoteAccess="false" />
    <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ELMAH" applicationName="myApplication"/>   
</elmah>

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

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

答案 6 :(得分:3)

有时CurrentHttpContext可能无法使用。

<强>定义

public class ElmahLogger : ILogger
{
    public void LogError(Exception ex, string contextualMessage = null, bool withinHttpContext = true)
    {
        try
        {
            var exc = contextualMessage == null 
                      ? ex 
                      : new ContextualElmahException(contextualMessage, ex);
            if (withinHttpContext)
                ErrorSignal.FromCurrentContext().Raise(exc);
            else
                ErrorLog.GetDefault(null).Log(new Error(exc));
        }
        catch { }
    }
}

使用

public class MyClass
{
    readonly ILogger _logger;

    public MyClass(ILogger logger)
    {
        _logger = logger;
    }

    public void MethodOne()
    {
        try
        {

        }
        catch (Exception ex)
        {
            _logger.LogError(ex, withinHttpContext: false);
        }
    }
}

答案 7 :(得分:2)

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

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

using ElmahCore;
...
HttpContext.RiseError(new Exception("Your Exception"));

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

using ElmahCore;
...
ElmahExtensions.RiseError(new Exception("Your Exception"));

答案 8 :(得分:0)

我试图使用Signal.FromCurrentContext()将自定义消息写入elmah日志.Raise(ex);并发现这些例外是冒泡的,例如:

try
{
    ...
}
catch (Exception ex)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
    // this will write to the log AND throw the exception
}

此外我没有看到elmah如何支持不同级别的日志记录 - 是否可以通过web.config设置关闭详细日志记录?

答案 9 :(得分:0)

使用了此行,效果很好。

 try{
            //Code which may throw an error
    }
    catch(Exception ex){
            ErrorLog.GetDefault(HttpContext.Current).Log(new Elmah.Error(ex));
    }