WebApi 2.1上的log4net使用ExceptionLogger

时间:2014-06-17 22:04:01

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

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

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

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

enter image description here

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

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

那么,如果使用全局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

1 个答案:

答案 0 :(得分:4)

建议不要使用获取堆栈跟踪的方法,因为代码在调试/发布或前置体系结构上的行为会有所不同。方法stackTrace.GetFrame(2).GetMethod()将为您提供实际堆栈上的方法,同时考虑处理器体系结构的运行时优化,linq重写等。

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

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

你应该看看这个问题:

stackframe-behaving-differently-in-release-mode