从 Log4Net 中删除顶层堆栈跟踪

Remove top levels of stacktrace from Log4Net

我有一个保存在 class 中的 log4net 实现,并且 class 是从静态 ExceptionHandler class 访问的(以避免更改一堆用法,因为这是遗留代码库)。因此,当记录异常时,它们看起来像这样:

System.Timers.Timer.MyTimerCallback > 
InternalMethod1 > 
InternalMethod2 > 
ExceptionHandler.HandleException > 
Logger.Log

我真的不希望最后两个出现在调用堆栈中,因为它们混淆了错误实际记录的位置,即 InternalMethod2。但是,我看到这样做的唯一方法是将实际记录器暴露给 InternalMethod2,我也不想这样做。

有什么方法可以管理我的堆栈跟踪以使其准确显示情况?

我的记录器Class:

public class Logger : ILogger
{
    public void Log(Exception ex, string message)
    {
        log4net.LogManager.Get("MyLog").Error(ex, message);
    }
}

我的异常处理程序class:

public static class ExceptionHandler
{
    private readonly static Logger MyLogger = new Logger();

    HandleException(Exception ex, string message)
    {
        MyLogger.Log(ex, message);
    }
}

我在InternalMethod2的来电:

void InternalMethod2()
{
    // do some stuff
    try
    {
        // do other stuff
    }
    catch (Exception e)
    {
        ExceptionHandler.HandleException(e, "An error occurred");
    }
}

根据文档 here%stacktrace 标记插入引用输出日志的方法的堆栈跟踪。这在使用与您不同的模式时很有用,即在每个 class 中插入一个 ILog。像这样:

private static log4net.ILog Logger = log4net.LogManager.GetLogger(typeof(ThisClass));

在输出异常详细信息时,您可以使用 %exception 令牌。

但是,我使用了一种稍微不同的方法:我使用 ILog 接口的扩展方法预先格式化异常详细信息。

    /// <summary>
    /// Logs an exception as an error in the provided logger,
    /// formatting message and stacktrace.
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="e"></param>
    public static void ErrorFromException(this ILog logger, Exception e)
    {
        ErrorFromException(logger, null, e);
    }

    /// <summary>
    /// Logs an exception as an error in the provided logger,
    /// formatting message and stacktrace.
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="prefix"></param>
    /// <param name="e"></param>
    public static void ErrorFromException(this ILog logger, string prefix, Exception e)
    {
        if (logger == null) return;

        if (e == null)
        {
            logger.Error(
                "LogExtension.ErrorFromException: A null exception was formatted. Probably there is a bug in the logging call.");
            return;
        }

        var sb = new StringBuilder(400);

        if (!String.IsNullOrEmpty(prefix))
            sb.AppendLine(prefix);

        sb.AppendLine("Caught exception (" + e.GetType().Name + "): " + e.Message);
        sb.AppendLine(e.StackTrace);

        var innerEx = e;

        while (innerEx.InnerException != null)
        {
            innerEx = innerEx.InnerException;
            sb.AppendLine("Inner exception (" + innerEx.GetType().Name + "): " + innerEx.Message);
            sb.AppendLine(innerEx.StackTrace);
        }

        sb.AppendLine();
        logger.Error(sb.ToString());
    }

希望对您有所帮助。