[slf4j-user] Why is there no NDC?

Ceki Gulcu ceki at qos.ch
Fri Jan 23 17:53:26 CET 2009



Joern Huxhorn wrote:
> Ceki Gulcu wrote:
>> Hello Joern,
>>
>> Did you know that NDC can be implemented on top of MDC? I just added
>> such an implementation into slf4j-ext. You can view it at:
>>
>> http://svn.slf4j.org/viewvc?view=rev&revision=1268
>>
> I'd implement NDC by using MDC the same way but it's obviously much less
> efficient than using a dedicated Stack (or ArrayList ) like in the log4j
> NDC.

It is indeed less efficient, and increasingly so as the stack size grows. In the 
tests I have performed, for a stack size of 3, I got the following results:

3.9 microseconds on average for direct calls to log4j's NDC with 3 pushes 
followed 3 pops
9.4 microseconds on average for NDC implemented via lMDC  for 3 pushes followed 
3 pops

For a stack size of 4,
direct log4j NDC: 5.6 microseconds on average for 4 push followed by 4 pop
indirectly via MDC: 17 microseconds on average for 4 push followed by 4 pops

Under logback, the performance is very similar, 17 microseconds for 4 pushes 
followed by 4 pops.

So, the cost is clearly higher but not appalling so.

> Moreover, it kind of "pollutes" the MDC by mixing MDC and NDC together.

Indeed. For example, MDC.clear() would also affect NDC.

> Well, I don't use NDC but I'd really like to :)
> It's not about which one is better but about which one is more suitable
> for a certain use case.

OK.

> They supplement each other. The NDC is something like a contextual stack
> trace while the MDC is a snapshot of some of the application data.
> 
> In our application, for example, we use the MDC to store the username,
> thee URL, the request-parameters and some other state information.
> 
> We write a proprietary CMS system where content can include other
> content and each of these have certain dynamic parts which need to be
> resolved. Therefore one use case for NDC would be to keep the nesting of
> the contents as well as informations about the various dynamic resolvers
> that could, again, load other contents..
> 
> An actual NDC would look something like this:
> Loading content A
> Loading content B
> Resolving dynamic values for X
> Loading content C
> 
> which would be of great use for us. Really. ;)

Thank you for clarifying this point.

Let me respond by observing that if you print the whole NDC stack on each log, 
they will take a lot of space (on each line), eventually causing eye sore.

If you think of it, NDC is just a thread local stack accessible by a conversion 
pattern of the underlying logging system. In logback, it is quite easy to 
register your own conversion pattern and conversion words. Search for "Creating 
a custom conversion specifier" in http://logback.qos.ch/manual/layouts.html

Given that you are using logback, you could create your own NDC implementation 
and associated conversion specifier. Once you have done that, you could print 
(log) NDC data at convenient times, for example every time the NDC data changes. 
(Your NDC code would use its own logger.)

Come to think of it, you don't even need your own conversion specifier. Your NDC 
implementation would simply convert the NDC stack into a string and log that as 
a message at appropriate times, for example when NDC changes.

> For example, if the loading of C failed we'd have the additional
> information that it could be related to the resolving of X that was done
> before.
> Using the NDC like this would also mean that we would push and pop quite
> often. Therefore the implementation of size(), which is called both in
> push and pop, would have a significant performance impact und would
> certainly perform *much* worse than just adding/removing to/from a
> thread-local List.

Although, it is true that there is a significant impact on performance, depends 
on what you mean by *much* worse. Anyway, I tend to agree with you.

[snip]
> I also suggested an NDC with lazy message formatting similar to logback
> logging messages. This would make a big difference if there was a place
> to globally disable NDC evaluation altogether or if NDC wasn't disabled
> but isn't used in any appender.

I think that writing your own NDC implementation would be the way to go in the 
use case you describe.

> Joern.

-- 
Ceki Gülcü
Logback: The reliable, generic, fast and flexible logging framework for Java.
http://logback.qos.ch



More information about the slf4j-user mailing list