Answers:
直接日志写入方法,自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.ErrorLog.Log()
:如果log调用本身失败,则抛出该异常,有可能使整个Web应用程序崩溃。Raise()
默默地失败。例如:如果服务器端存在配置错误的问题(例如,Elmah配置为将错误保存到磁盘,但没有对logs文件夹的正确访问权限),则该.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);
}
这具有以下好处:
注意:我添加了一个“ contextualMessage”属性来获取上下文信息。如果愿意,可以省略此选项,但我认为它非常有用。Elmah自动解包异常,因此基础异常仍将在日志中报告,但单击上下文上下文消息将可见。
// uh oh! just keep going
。如果我的错误处理失败,我想知道。我希望它发出一些声音。
catch(Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
我一直在寻找从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));
}
});
packages.config
长什么样?你看到类似的东西<package id="elmah" version="1.2.2" targetFramework="net45" />
<package id="elmah.corelibrary" version="1.2.2" targetFramework="net45" />
<package id="elmah.sqlserver" version="1.2" targetFramework="net45" />'
吗?您安装了NuGET吗?
packages.config
有时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()。Raise(ex);将自定义消息写入Elmah日志。并发现这些异常已冒出,例如:
try
{
...
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
// this will write to the log AND throw the exception
}
此外,我看不到elmah如何支持不同级别的日志记录-是否可以通过web.config设置关闭详细日志记录?