【问题标题】:log4net on WebApi 2.1 using ExceptionLogger使用 ExceptionLogger 在 WebApi 2.1 上的 log4net
【发布时间】:2014-06-17 22:04:01
【问题描述】:

如何正确实现 WebApi 2.1 的 ExceptionLogger 以便 log4net 记录方法、位置和行的正确值?

我想要实现的是一个全局异常记录器,用于在运行 .NET 4.5.1 的 WebAPI 2.1 v5.1.2 应用程序中记录所有未处理的异常。我已经阅读了很多文章,包括下面链接的一篇解释如何实现 ExceptionLogger 的文章,它工作得很好,除了我无法让 log4net 输出我真正想要记录的值。

例如,如果我从控制器记录异常,则一切正常。当我从 ExceptionLogger 记录时,我从 Logger 本身获取值,而不是从引发异常的方法。我尝试了下面代码中列出的一些东西,但它们并不完全正确。这就是我得到的。

我知道文本很小,但表格显示了 log4net 写入的不同值。第一个日志来自控制器,一切都很好。第二个条目来自代码 sn-p 中的 log.Logger.Log。最后一个条目来自 log.Error 中的 sn-p。

sn-p 中的最后一个方法尝试使用我从 log4net 包装器的其他实现中读取的限制类型,但它只是抛出错误,如 sn-p 中所述。

那么,在使用 GLOBAL ExceptionLogger 时,我如何获得与从控制器调用时收到的值一样的值?

public class GlobalExceptionLogger: ExceptionLogger
{
    //private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    public override void Log(ExceptionLoggerContext context)
    {
        StackTrace stackTrace = new StackTrace(context.Exception);
        Type methodDeclaringType = stackTrace.GetFrame(2).GetMethod().DeclaringType;

        ILog log = LogManager.GetLogger(methodDeclaringType);
        string message = context.ExceptionContext.Exception.Message;

        //this methods works but writes the location, method name and line from this method, not the caller
        //location: System.Web.Http.ExceptionHandling.ExceptionLogger.LogAsync(:0)
        //method: LogAsync
        //line: 0
        log.Logger.Log(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, log4net.Core.Level.Error, message, context.ExceptionContext.Exception);


        //this methods works but writes the location, method name and line from this method, not the caller
        //location: Company.AppName.Api.GlobalExceptionLogger.Log(c:\TFS\AppName\AppName.Api\GlobalExceptionLogger.cs:38)
        //method: Log
        //line: 38
        log.Error(message, context.ExceptionContext.Exception);

        //this method throws an error in the log4net debug: log4net:ERROR loggingEvent.LocationInformation.StackFrames was null or empty.
        log.Logger.Log(methodDeclaringType, log4net.Core.Level.Error, message, context.ExceptionContext.Exception);
    }

}

http://weblogs.asp.net/jongalloway//looking-at-asp-net-mvc-5-1-and-web-api-2-1-part-4-web-api-help-pages-bson-and-global-error-handling

【问题讨论】:

  • 有趣的笔记。如果我使用 Type methodDeclaringType = new StackTrace().GetFrame(2).GetMethod().DeclaringType; ,这将防止最后一个方法出错。但是,此堆栈跟踪与创建堆栈跟踪(上下文.异常)时不同。这让我相信 Logger.Log 没有使用作为传入异常一部分的堆栈跟踪,而是来自其他一些来源。

标签: asp.net-web-api log4net asp.net-web-api2 exception-logging


【解决方案1】:

不推荐您获取堆栈跟踪的方法,因为代码在调试/发布或前驱架构上的行为会有所不同。方法 stackTrace.GetFrame(2).GetMethod() 将为您提供真实堆栈上的方法,同时考虑到处理器架构的运行时优化、linq 重写等。

获取成员名称的另一种方法:

public static string LogError(Exception ex, [CallerMemberName] string callerName = "")

你应该看看这个问题:

stackframe-behaving-differently-in-release-mode

【讨论】:

  • 了解堆栈跟踪,但这来自其他解释如何在包装器内操作 log4net 的帖子。不幸的是,您的替代方法不起作用,因为在覆盖 IExceptionLogger 的 Log 方法时无法添加新参数。对我来说,尝试使用 log4net 进行全局错误记录并不是一个好主意,这一点变得越来越明显。我已经开始使用 Elmah 进行错误记录,但如果我的通用记录器和错误记录器可以记录到同一个数据库,这样我就可以查看历史记录而不仅仅是错误,这似乎会很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-10
  • 1970-01-01
  • 2018-05-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多