如何使用ELMAH手动logging错误

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

logger.Log(" something"); 

我正在做这样的事情:

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

ELMAH不会自动logging此exception,因为它已被处理。

直接的日志写入方法,从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); } 

这两个解决scheme之间有一个区别:

  • Raise方法将ELMAH过滤规则应用于exception。 Log方法不。
  • Raise是基于订阅的,并且能够将一个exceptionlogging到多个logging器中。

我build议在你自己的一个简单的包装类包装电话给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 } } } 

那么只要你需要logging一个错误就打电话给它。

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

这有以下好处:

  • 你不需要记住这个Elmah调用的这个稍微陈旧的语法
  • 如果你有很多DLL,你不需要从每一个引用Elmah核心 – 只要把它放在你自己的“系统”DLL中。
  • 如果你需要做任何特殊的处理,或者只是想放置一个断点来debugging错误,那么你只需要一个地方。
  • 如果你离开Elmah,你可以改变一个地方。
  • 如果你有遗留的错误日志logging,你想保留(我只是碰巧有一个简单的错误logging机制,绑定到一些用户界面,我不马上有时间去除)。

注意:我已经为上下文信息添加了“contextualMessage”属性。 你可以省略这个,如果你喜欢,但我觉得它非常有用。 Elmah会自动解开exception,这样底层的exception仍然会在日志中报告,但是当你点击它时,contextualMessage将会显示。

您可以使用Elmah.ErrorSignal()方法logging问题而不引发exception。

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

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

一个小例子:

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

我正在寻找在线程中做同样的事情,我已经开始排队从我的MVC4应用程序的邮件,因为我没有HttpContext提供exception时可用。 要做到这一点,我结束了以下基于这个问题和另一个答案在这里find: elmah:没有HttpContext的exception?

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

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

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

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

另外,我不明白如何elmah支持不同级别的日志logging – 是否有可能通过web.config设置closures详细日志logging?