如何使用树状结构进行日志记录

时间:2016-07-26 07:41:38

标签: c# logging tree log4net

我想用log4net(我现在正在这样做)登录到一个文件,但是使用log4net,只有简单的日志输出,每行都有一条消息。

现在我想登录到同一个日志文件,但是在树状结构中。例如,我有以下方法调用,每个方法都记录其方法名称(应该有缩进):

firstMethod().secondMethod().thirdMethod();

应打印此日志,例如:

2016-07-26 15:44:56,042    > firstMethod
2016-07-26 15:44:56,043         > secondMethod
2016-07-26 15:44:56,044              > thirdMethod
2016-07-26 15:44:56,045              < thirdMethod
2016-07-26 15:44:56,046         < secondMethod
2016-07-26 15:44:56,047    < firstMethod

在方法的开头和结尾处的方法中打印<>符号。

3 个答案:

答案 0 :(得分:0)

效率不高,但您可以查看使用调用堆栈获取方法的层次结构,然后根据调用堆栈中调用的深度填充/缩进每个日志条目。

 StackTrace stackTrace = new StackTrace();          
 StackFrame[] stackFrames = stackTrace.GetFrames();

替代方案可能包括使用PostSharp或(可能)编写a custom appender for log4net。另一个想法是忘记缩进并使用完整的命名空间和方法名来跟踪日志条目的来源。通过这种方式,您仍然可以看到树状视图。

var methodInfo = System.Reflection.MethodBase.GetCurrentMethod();
var fullName = methodInfo.DeclaringType.FullName + "." + methodInfo.Name;

所有这一切,似乎是一个非常典型的要求。你真的需要这样做吗?

答案 1 :(得分:0)

如何使用参数输入/退出添加另一种方法进行日志记录,并在那里执行填充:

int curLevel = 0;
public void MyLogInfo( bool enter, [System.Runtime.CompilerServices.CallerMemberName] string callingMethod = "", )
{
    string prefix;
    if (enter)
    {
      prefix = "> ";
      curLevel++;
    }
    else
    {
      prefix = "< ";
      curLevel--;
    }
    logger.info(prefix.PadLeft(curLevel+prefix.Length) + callingMethod);
}

您只需调用MyLogInfo(true)或MyLogInfo(false) - 如果您没有自己指定,.NET将设置callingMethod名称。

你必须确保你总是在你记录的每个方法的进入/退出时调用方法 - 也许检查你不要将curLevel减少到零以下。

答案 2 :(得分:0)

您可以使用 NDC 来实现类似的行为。但它已被弃用。现在,您可以使用上下文和上下文堆栈。查看此文档:https://logging.apache.org/log4net/release/manual/contexts.html

您可以定义多个堆栈(而不是缩进)。您要调试的一组行为的一个堆栈。假设您想记录创建销售订单及其项目的日志。在这个例子中,这个堆栈是在 ThreadContext 中定义的。但是,您可以在 GlobalContext 、 LogicalThreadContext 或 LoggingEvent 中定义它。

using(log4net.ThreadContext.Stacks["SalesOrderLogic"].Push("SalesOrder"))
{
    log.Info("Created the sales order");

    using(log4net.ThreadContext.Stacks["SalesOrderLogic"].Push("Items"))
    {
        log.Info("Created the sales order items");
    }
}

然后你应该把它添加到你的配置中:

<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%logger - %property{SalesOrderStatus} - [%level]- %message%newline" />
  </layout>
</appender>

免责声明:我没有测试这段代码。

注 1:旧的 NDC 将出现在一个线程中。因此,如果您在一个线程中推送消息,它将不会出现在另一个线程中。与新的 Context Stack 方法不同,它只有一个堆栈。

注意 2:不要忘记检查上下文。很有用。

注意 3:如果你研究 Ninject 和 log4net 一起工作,你可能会发现它很有用