[ACCEPTED]-When to use 'nested diagnostic context' (NDC)?-ndc
Want an example?
Take the following Web API 11 written using ASP.NET MVC4:
// 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 10 HTTP Requests are made, the logging can 9 get interleaved. E.g.
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 8 could use the thread id to distinguish requests, but 7 that can get tricky as the log file grows 6 in complexity.
A better alternative is 5 to provide unique identifiers that group 4 together log messages for the same request. We 3 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 2 produces a log that you can grep to see 1 the issues associated with a specific request. E.g.
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
In a server application such as ASP.NET.
For 2 example, you can push information about 1 the current request on to the NDC.
These feature come in handy when you have 10 lots of logs to go through. When would you 9 have lots of logs? Diagnosing weird bug 8 on a production system with interleaving 7 outputs. Having more contexts gives you 6 way to filter the output or not outputting 5 unneeded logs.
Another case nested contexts 4 could be useful is if a method or some feature 3 is called several times in different contexts 2 and you need a way to distinguish between 1 them.
NDC.Push
has been deprecated. The preferred way 2 now (ThreadContext.Stacks["NDC"]
) is this:
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 1 pattern so that it includes %property{NDC}
:
<layout type="log4net.Layout.PatternLayout">
<conversionPattern
value="%date [%2thread] %-5level [%property{NDC}] - %.10240message%newline" />
</layout>
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.