.net 何时使用';嵌套诊断上下文';(国家数据中心)?

.net 何时使用';嵌套诊断上下文';(国家数据中心)?,.net,logging,log4net,ndc,.net,Logging,Log4net,Ndc,通过使用log4net,我看到了使用一个称为NDC的每线程上下文标签堆栈的可能性 通过指定%x或%ndc格式参数,推送到该堆栈上的标签将显示在PatternLayout中 用法类似于: ILog log = log4net.LogManager.GetLogger(...) ; //pattern layout format: "[%ndc] - %message%newline" log.Info("message 1"); using(log4net.NDC.Push("context

通过使用log4net,我看到了使用一个称为NDC的每线程上下文标签堆栈的可能性

通过指定
%x
%ndc
格式参数,推送到该堆栈上的标签将显示在PatternLayout中

用法类似于:

ILog log = log4net.LogManager.GetLogger(...) ;

//pattern layout format: "[%ndc] - %message%newline"

log.Info("message 1"); 
using(log4net.NDC.Push("context")
{
    using(log4net.NDC.Push("inner_context")
    {
      log.Info("message 2"); 
    }
    log.Info("message 3"); 
}
log.Info("message 4"); 
输出类似于:

null - message 1
context inner_context - message 2
context - message 3
null - message 4

在您使用log4net的编程体验中,您什么时候发现此功能有用?

当您有大量日志需要查看时,这些功能会派上用场。你什么时候会有很多日志?诊断具有交错输出的生产系统上的奇怪错误。拥有更多的上下文可以让您过滤输出,或者不输出不需要的日志


另一种情况是,如果在不同的上下文中多次调用某个方法或某个功能,并且您需要一种方法来区分它们,则嵌套上下文可能很有用。

在ASP.NET等服务器应用程序中

例如,您可以将有关当前请求的信息推送到NDC。

想要一个示例吗

以使用ASP.NET MVC4编写的以下Web API为例:

// GET api/HypervResource
public string Get()
{
    logger.Debug("Start of service test");
    System.Threading.Thread.Sleep(5000); // simulate work
    logger.Debug("End of service test");
    return "HypervResource controller running, use POST to send JSON encoded RPCs";
}
当发出服务器并发HTTP请求时,日志记录可以交错进行。例如

2013-06-27 13:28:11,967 [10] DEBUG HypervResource.WmiCalls [(null)] - Start of service test
2013-06-27 13:28:12,976 [12] DEBUG HypervResource.WmiCalls [(null)] - Start of service test
2013-06-27 13:28:14,116 [13] DEBUG HypervResource.WmiCalls [(null)] - Start of service test
2013-06-27 13:28:16,971 [10] DEBUG HypervResource.WmiCalls [(null)] - End of service test
2013-06-27 13:28:17,979 [12] DEBUG HypervResource.WmiCalls [(null)] - End of service test
2013-06-27 13:28:19,119 [13] DEBUG HypervResource.WmiCalls [(null)] - End of service test
在这个简单的示例中,您可以使用线程id来区分请求,但随着日志文件复杂性的增加,这可能会变得棘手

更好的选择是提供唯一标识符,将同一请求的日志消息分组在一起。我们可以更新以下代码:

// GET api/HypervResource
public string Get()
{
    using(log4net.NDC.Push(Guid.NewGuid().ToString()))
    {
        logger.Debug("Start of service test");
        System.Threading.Thread.Sleep(5000); // simulate work
        logger.Debug("End of service test");
        return "HypervResource controller running, use POST to send JSON encoded RPCs";
    }
}
这将生成一个日志,您可以通过grep查看与特定请求相关的问题。例如

2013-06-27 14:04:31,431 [11] DEBUG HypervResource.WmiCalls [525943cb-226a-43c2-8bd5-03c258d58a79] - Start of service test
2013-06-27 14:04:32,322 [12] DEBUG HypervResource.WmiCalls [5a8941ee-6e26-4c1d-a1dc-b4d9b776630d] - Start of service test
2013-06-27 14:04:34,450 [13] DEBUG HypervResource.WmiCalls [ff2246f1-04bc-4451-9e40-6aa1efb94073] - Start of service test
2013-06-27 14:04:36,434 [11] DEBUG HypervResource.WmiCalls [525943cb-226a-43c2-8bd5-03c258d58a79] - End of service test
2013-06-27 14:04:37,325 [12] DEBUG HypervResource.WmiCalls [5a8941ee-6e26-4c1d-a1dc-b4d9b776630d] - End of service test
2013-06-27 14:04:39,453 [13] DEBUG HypervResource.WmiCalls [ff2246f1-04bc-4451-9e40-6aa1efb94073] - End of service test

NDC.Push
已被弃用。现在首选的方式(
ThreadContext.Stacks[“NDC”]
)是:

var disposable=ThreadContext.Stacks[“NDC”].Push(“context”);
尝试
{
Log.Info(“begin”);//可选,但很好
...
}
最后
{
Log.Info(“end”);//可选,但很好
一次性的,一次性的;
}
请记住检查转换模式,使其包括
%property{NDC}

<layout type="log4net.Layout.PatternLayout">
  <conversionPattern
    value="%date [%2thread] %-5level [%property{NDC}] - %.10240message%newline" />
</layout>


一个指向示例的链接会很有用我没有链接,但请考虑这样一种情况,即您有一个ASP.NET应用程序,其中有许多同时处理的请求。如果将请求ID(生成的或使用请求中的某个标识符)推送到NDC,则可以通过应用程序的所有级别关联给定请求的所有日志消息。因此,现在来自不了解ASP.NET的低级组件的日志消息可以关联回原始请求。@Johnny\D,例如?看起来log4net已经弃用了NDC,取而代之的是通用上下文堆栈。答案中的建议仍然正确,但表示“NDC(嵌套诊断上下文)的存在是为了与旧版本的log4net兼容。此帮助器类实现了一个堆栈,该堆栈存储在名为NDC的线程上下文属性中。”@MichaelLevy我在下面讨论的一般原则保持不变。因此NDC.Push(“上下文”)已被ThreadContext.Stacks[“NDC”].Push(“上下文”)替换,并且在转换模式中,值[%NDC]或%x被[%property{NDC}]替换,这被认为是一个进步?第一印象,我同意@haughtonomous,但在阅读了它之后:1-新方法也可以写入using语句中。2-NDC将仅在线程上下文中工作。3-现在,您可以定义多个堆栈,而不是一个堆栈。在这里查看我的答案: