【问题标题】:Remove top levels of stacktrace from Log4Net从 Log4Net 中删除堆栈跟踪的顶层
【发布时间】:2018-08-22 17:02:18
【问题描述】:

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

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

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

有没有一种方法可以整理我的堆栈跟踪,以便准确地显示情况?

我的记录器类:

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

我的 ExceptionHandler 类:

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");
    }
}

【问题讨论】:

  • 能否将代码包含在 ExceptionHandler、Logger.Log 和 InternalMethod2 示例中?
  • @A.Chiesa 我已经这样做了。如您所见,调用堆栈将显示在我的记录器类中“抛出”的异常。此外,%location 变量将显示我的记录器类的位置
  • 代码是完整的还是简化的?您的代码中没有任何内容可能会更改异常的堆栈跟踪。寻找throw e; 呼叫而不是throw;
  • @A.Chiesa 代码已简化,但所有throw 语句都出现在方法内或方法调用的方法内。我在进行转换时发现了几个throw e; 语句,我更改了这些语句,但Logger.Log 中没有出现任何语句。此外,我正在谈论的堆栈跟踪是一个 log4net 变量,所以我不确定它是如何设置的
  • 您使用了错误的模式:%exception 标记格式化异常文本包括异常的堆栈跟踪。相反,您使用的是 %stacktrace 令牌,根据文档 (logging.apache.org/log4net/release/sdk/?topic=html/…),它指的是日志调用的堆栈跟踪。就个人而言,我更喜欢自己预先格式化异常,解开最终的内部异常,为包中的每个异常记录消息和堆栈跟踪。

标签: c# logging log4net


【解决方案1】:

根据文档here%stacktrace 标记插入引用输出日志的方法的堆栈跟踪。这在使用与您不同的模式时很有用,即在每个类中插入 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());
    }

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多