Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用ELMAH手动记录错误_C#_Exception Handling_Elmah_Error Logging - Fatal编程技术网

C# 如何使用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) {

是否可以使用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)
{
    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);
}
两种解决方案之间存在差异:

  • Raise
    方法将ELMAH筛选规则应用于异常<代码>日志方法不适用
  • 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
        }
    }
}
这有以下好处:

  • 您不需要记住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
,以供将来参考,我写了一篇文章,正是关于这一点:。我也有一些关于这个的信息。如果你捕捉到一个异常并且不再抛出它,除了