C# 如何使用ELMAH手动记录错误
是否可以使用ELMAH执行以下操作C# 如何使用ELMAH手动记录错误,c#,exception-handling,elmah,error-logging,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不会自动记录此异常,因为它已被处理。您可以使用ELMAH.ErrorSignal()方法记录问题,而不会引发异常 catch(Exception ex) {
logger.Log(" something");
我在做这样的事情:
try
{
// Code that might throw an exception
}
catch(Exception ex)
{
// I need to log error here...
}
ELMAH不会自动记录此异常,因为它已被处理。您可以使用ELMAH.ErrorSignal()方法记录问题,而不会引发异常
catch(Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
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);
}
两种解决方案之间存在差异:
方法将ELMAH筛选规则应用于异常<代码>日志方法不适用Raise
基于订阅,能够将一个异常记录到多个记录器中Raise
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
}
}
}
这有以下好处:
- 您不需要记住Elmah调用的这种略显陈旧的语法
- 如果你有很多DLL,你不需要从每一个DLL中引用Elmah Core,只要把它放在你自己的“系统”DLL中就行了
- 如果您需要进行任何特殊处理,或者只想设置断点来调试错误,那么您可以将其放在同一个位置
- 如果你离开艾玛,你可以换一个地方
- 如果您想要保留遗留的错误日志记录(我正好有一个简单的错误日志记录机制,它绑定到一些UI中,我没有时间立即删除)
注意:我为上下文信息添加了一个“contextualMessage”属性。如果你愿意,可以省略这个,但我觉得它很有用。Elmah会自动打开异常,因此日志中仍会报告底层异常,但当您单击它时,上下文消息将可见。我希望在一个线程中执行相同的操作,我已开始从MVC4应用程序中对邮件进行排队,因此,在引发异常时,我没有可用的HttpContext。为了做到这一点,我根据这个问题和这里的另一个答案得出以下结论: 在配置文件中,我指定了一个应用程序名称:
<elmah>
<security allowRemoteAccess="false" />
<errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ELMAH" applicationName="myApplication"/>
</elmah>
有时,
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);
}
}
}
使用
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设置关闭详细日志记录?我使用的是ASP.NET core,我使用的是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));
}
您的方法与其他方法有什么不同?这些方法在Elmah中记录错误,而不会导致应用程序停止工作。它允许您捕获常见异常,正确处理它们,但仍然能够记录它们。我发现,当回发包含针对Mvc4.Net 4.5的不安全Html时,Elmah.ErrorSignal没有记录,在我的示例中,是来自Windows访问控制服务的回发,带有SignInResponseMessage。Elmah.ErrorLog.GetDefault确实在该场景中起作用,我对不安全的Html也有同样的问题。ErrorLog.GetDefault在使用
Elmah.ErrorLog.Log()
时做了trickOne的大警告:如果日志调用本身失败,它会抛出错误,可能会导致整个web应用程序崩溃<代码>升起()以静默方式失败。例如:如果服务器端存在错误配置问题(例如,Elmah被配置为将错误保存到磁盘,但没有对日志文件夹的正确访问权限),将抛出.Log()
方法。(这对调试很有好处,例如为什么.Raise()
不记录任何内容?)回答得很好。也许ELMAH应该实现类似的开箱即用。有时候,在没有上下文的情况下调试一个错误是非常困难的。我喜欢用//嗯,哦,几乎吞下任何次要错误!继续前进
。如果我的错误处理失败,我想知道。我想让它制造一些噪音。@JeremyCook我同意,但要注意的是,如果你不小心,失败的错误处理例程往往会自己调用,然后崩溃(哦,我实际上也在这里调用第三方API来记录错误)。我可能不应该为了这个答案而留下这个,但我以前有过这样的不好的经历,作为一种扩展方法,它会更好。你可能会想:不,我可以尝试记录多少手动错误?我想,大约一年前。长话短说:用这个包装!我喜欢你的解决方案;然而,我无法在我的项目中解决“Elmah”。我尝试在我的代码中添加“using Elmah;”,但它在我当前的上下文中不存在。@Taersious您的packages.config
看起来像什么?您是否看到类似这样的内容:
”
?你是用NuGET安装的吗?我想说是的,但我的项目目前被锁定在源代码管理中。我从项目中的示例配置文件手动实现了elmah。@Taersious如果是手动实现的,在调用using。。。我希望它能以任何一种方式工作,但我知道,当nuget添加它时,上面的行会被添加到packages.config
,以供将来参考,我写了一篇文章,正是关于这一点:。我也有一些关于这个的信息。如果你捕捉到一个异常并且不再抛出它,除了