如何使用ELMAH手动记录错误

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

logger.Log(" something");

我是这样做的:

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

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

100812 次浏览
catch(Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}

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

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


// Continue
}

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

举个小例子:

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

直接日志写入方法,自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是基于订阅的,能够将一个异常记录到多个记录器中。

我建议在您自己的一个简单的包装类中包装对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,你不需要从每个DLL中引用Elmah Core,只需要把它放在你自己的“系统”DLL中。
  • 如果您需要进行任何特殊处理,或者只是想设置一个断点来调试错误,那么您可以在一个地方完成所有操作。
  • 如果你要离开埃尔玛你可以换一个地方。
  • 如果你想保留遗留的错误记录(我只是碰巧有一个简单的错误记录机制,它绑定到一些我没有时间立即删除的ui中)。

注意:我为上下文信息添加了一个'contextualMessage'属性。如果你愿意,你可以省略这个,但我发现它非常有用。Elmah自动展开异常,因此底层异常仍将在日志中报告,但当您单击contextualMessage时将可见。

我希望在一个线程中做同样的事情,我已经开始从我的MVC4应用程序中排队邮件,因此当异常被引发时,我没有HttpContext可用。为了做到这一点,我最终根据这个问题和在这里找到的另一个答案:elmah:异常没有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));
}
});

有时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);
}
}
}

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

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

此外,我不知道elmah是如何支持不同级别的日志记录的——是否有可能通过web关闭详细日志记录。配置设置?

我在ASP。网络核心上,我使用ElmahCore

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

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

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

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

使用这条线,它工作得非常好。

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