如何使用 ELMAH 手动记录错误

发布于 2024-12-04 18:23:26 字数 269 浏览 5 评论 0原文

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

logger.Log(" something");

我正在做这样的事情:

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

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

Is it possible to do the following using ELMAH?

logger.Log(" something");

I'm doing something like this:

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

This exception will not be automatically logged by ELMAH, because it was handled.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

风蛊 2024-12-11 18:23:27

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

Direct log writing method, working since ELMAH 1.0:

try 
{
    some code 
}
catch(Exception ex)
{
    Elmah.ErrorLog.GetDefault(HttpContext.Current).Log(new Elmah.Error(ex));
}

ELMAH 1.2 introduces a more flexible API:

try 
{
    some code 
}
catch(Exception ex)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}

There is a difference between the two solutions:

  • Raise method applies ELMAH filtering rules to the exception. Log method does not.
  • Raise is subscription based and is able to log one exception into the several loggers.
逆流 2024-12-11 18:23:27

我建议将对 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。
  • 如果您需要执行任何特殊处理或只是想放入断点来调试错误,那么您可以将所有这些都放在一处。
  • 如果您离开 Elmah,只需换一个地方即可。
  • 如果您有想要保留的遗留错误日志记录(我只是碰巧有一个简单的错误日志记录机制,该机制与一些我没有时间立即删除的 UI 相关联)。

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

I'd recommend wrapping the call to Elmah in a simple wrapper class of your own.

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

Then just call it whenever you need to log an error.

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

This has the following benefits:

  • You don't need to remember this slightly archaic syntax of the Elmah call
  • If you have many DLLs you don't need to reference Elmah Core from every single one - and just put this in your own 'System' DLL.
  • If you ever need to do any special handling or just want to put in a breakpoint to debug errors you have it all one place.
  • If you ever move away from Elmah you can just change one place.
  • If you have legacy error logging you want to retain (I just happen to have a simple error logging mechanism that's tied into some UIs that I dont immediately have time to remove).

Note: I've added a 'contextualMessage' property for contextual information. You can omit this if you prefer but I find it very useful. Elmah automatically unwraps exceptions so the underlying exception will still be reported in the log but the contextualMessage will be visible when you click on it.

沙与沫 2024-12-11 18:23:27

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

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

    // Continue
}

You can use the Elmah.ErrorSignal() method to log an issue without raising an exception.

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

    // Continue
}
○愚か者の日 2024-12-11 18:23:27
catch(Exception ex)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
catch(Exception ex)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
沉睡月亮 2024-12-11 18:23:27

我使用 ASP.NET core,并使用 ElmahCore

使用 HttpContext(在控制器中)手动记录错误,只需编写:

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

在应用程序的另一部分不使用 HttpContext

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

I am on ASP.NET core and I use ElmahCore.

To manually log errors with HttpContext (in controller) simply write:

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

In another part of your application without HttpContext:

using ElmahCore;
...
ElmahExtensions.RiseError(new Exception("Your Exception"));
酷炫老祖宗 2024-12-11 18:23:27

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

一个小例子:

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

Yes, it is possible. ELMAH was designed to intercept unhandled exceptions. However you can signal an exception to ELMAH via the ErrorSignal class. Those exceptions are not thrown (don't bubble up), but are only sent out to ELMAH (and to subscribers of the Raise event of the ErrorSignal class).

A small example:

protected void ThrowExceptionAndSignalElmah()
{
    ErrorSignal.FromCurrentContext().Raise(new NotSupportedException());
}
貪欢 2024-12-11 18:23:27

我希望在一个线程中做同样的事情,我已经开始从 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));
     }
 });

I was looking to do this same thing in a thread I had started to queue mail from within my MVC4 application, as such I did not have the HttpContext available when an exception was raised. To do this I ended up with the following based on this question and another answer found on here: elmah: exceptions without HttpContext?

In the config file I specified an application name:

<elmah>
    <security allowRemoteAccess="false" />
    <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ELMAH" applicationName="myApplication"/>   
</elmah>

Then in code (like the answer provided above, but without the HttpContext) you can pass null instead of an HttpContext:

ThreadPool.QueueUserWorkItem(t => {
     try {
         ...
         mySmtpClient.Send(message);
     } catch (SomeException e) {
         Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(e));
     }
 });
笑忘罢 2024-12-11 18:23:27

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

Sometimes CurrentHttpContext may not be available.

Define

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 { }
    }
}

Use

public class MyClass
{
    readonly ILogger _logger;

    public MyClass(ILogger logger)
    {
        _logger = logger;
    }

    public void MethodOne()
    {
        try
        {

        }
        catch (Exception ex)
        {
            _logger.LogError(ex, withinHttpContext: false);
        }
    }
}
烟若柳尘 2024-12-11 18:23:27

我试图使用 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 设置关闭详细日志记录?

I was trying to write custom messages into elmah logs using Signal.FromCurrentContext().Raise(ex); and found that these exceptions are bubbled up, eg:

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

Besides I don't see how elmah supports different levels of logging - is it possible to switch off verbose logging by a web.config setting?

暮光沉寂 2024-12-11 18:23:27

使用了这条线,效果非常好。

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

Used this line and it works perfectly fine.

 try{
            //Code which may throw an error
    }
    catch(Exception ex){
            ErrorLog.GetDefault(HttpContext.Current).Log(new Elmah.Error(ex));
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文