.net 何时使用“嵌套诊断上下文”(NDC)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/334367/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 10:44:13  来源:igfitidea点击:

When to use 'nested diagnostic context' (NDC)?

.netlogginglog4netndc

提问by Cristian Diaconescu

Playing with log4net, I have seen the possibility to use a per-thread stack of context labels called the NDC.

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

The labels pushed on this stack are displayed in a PatternLayout by specifying the %xor the %ndcformat parameter.

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

The usage is something like:

用法类似于:

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

The output is something like:

输出类似于:

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

In your programming experience with log4net, when did you find this feature to be useful?

在您使用 log4net 的编程经验中,您何时发现此功能很有用?

采纳答案by Joe

In a server application such as ASP.NET.

在诸如 ASP.NET 之类的服务器应用程序中。

For example, you can push information about the current request on to the NDC.

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

回答by Donal Lafferty

Want an example?

想要一个例子?

Take the following Web API written using ASP.NET MVC4:

以使用 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";
}

When server concurrent HTTP Requests are made, the logging can get interleaved. E.g.

当发出服务器并发 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

In this simple example, you could use the thread id to distinguish requests, but that can get tricky as the log file grows in complexity.

在这个简单的示例中,您可以使用线程 ID 来区分请求,但是随着日志文件的复杂性增加,这可能会变得棘手。

A better alternative is to provide unique identifiers that group together log messages for the same request. We can update the code as to the following:

更好的替代方法是提供唯一标识符,将同一请求的日志消息组合在一起。我们可以将代码更新为以下内容:

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

This produces a log that you can grep to see the issues associated with a specific request. E.g.

这会生成一个日志,您可以通过 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

回答by Eugene Yokota

These feature come in handy when you have lots of logs to go through. When would you have lots of logs? Diagnosing weird bug on a production system with interleaving outputs. Having more contexts gives you way to filter the output or not outputting unneeded logs.

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

Another case nested contexts could be useful is if a method or some feature is called several times in different contexts and you need a way to distinguish between them.

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

回答by Daniel Lidstr?m

NDC.Pushhas been deprecated. The preferred way now (ThreadContext.Stacks["NDC"]) is this:

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

var disposable = ThreadContext.Stacks["NDC"].Push("context");
try
{
  Log.Info("begin"); // optional, but nice
  ...
}
finally
{
  Log.Info("end"); // optional, but nice
  disposable.Dispose();
}

Remember to check your conversion pattern so that it includes %property{NDC}:

请记住检查您的转换模式,使其包括%property{NDC}

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