2

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

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

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

在此处输入图像描述

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

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

那么,当使用 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 -和全局错误处理

4

1 回答 1

4

Your method of getting the stacktrace is not recommended, because the code will behave differently on debug/release or precessor architecture. The method stackTrace.GetFrame(2).GetMethod() will give you the method on the real stack, with taking into consideration the optimalizations of the runtime for processor architecture, linq rewrites etc.

An alternative method of getting the member name:

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

You should have a look at this question:

stackframe-behaving-differently-in-release-mode

于 2014-06-18T10:11:59.703 回答