[slf4j-user] Why is there no NDC?
Joern Huxhorn
jhuxhorn at googlemail.com
Fri Jan 23 00:43:58 CET 2009
Just for reference: A better version of my example would be the
following because it would handle varargs:
====================================
import org.slf4j.NDC;
def withNdc =
{
String messagePattern, Object[] args ->
Closure operation=null;
if(args)
{
Object lastArg=args[args.length-1];
if(lastArg instanceof Closure)
{
operation=(Closure)lastArg;
if(args.length>1)
{
args=args[0..args.length-2]
}
else
{
args=null;
}
}
}
NDC.push(messagePattern, (Object[])args)
try
{
if(operation)
{
operation()
}
}
finally
{
NDC.pop()
}
}
withNdc("Parameters are {} and {}.", "foo", "bar")
{
// NDC has the message "Parameter is bar." pushed. In case of
Logback, I would postpone the actual formatting until the formatted
message is really needed/used by an appender (like in LoggingEvent)...
}
// NDC has been popped.
====================================
On 22.01.2009, at 23:26, Joern Huxhorn wrote:
> Hi Ceki,
>
> I guess that a piece of actual code is the easiest way to explain
> what I mean.
>
> The following is valid Groovy code, using MDC as an example:
> ====================================
> import org.slf4j.MDC;
>
> def withValue =
> {
> String key, String value, Closure operation ->
>
> MDC.put(key, value)
> try
> {
> operation()
> }
> finally
> {
> MDC.remove(key)
> }
> }
>
> withValue("foo","bar")
> {
> // MDC contains the key "foo" with the value "bar"
> assert MDC.get("foo") == "bar"
> }
>
> assert !MDC.get("foo") // MDC does not contain the key "foo" anymore
> ====================================
>
> This means that the MDC will contain the given key, value for the
> duration of the operation in the following scope, ensuring to
> *always* remove the value again, even in case of an exception.
> Another use-case would be to get the old value before putting the
> new one and restoring it instead of just removing.
> Those closures, while syntactically a little awkward, are extremely
> powerful.
>
> So what I meant in my previous mail would be something like this
> (and this time I didn't check it for correctness, obviously:
> ====================================
> import org.slf4j.NDC;
>
> def withNdc =
> {
> String messagePattern, Object[] args, Closure operation ->
>
> NDC.push(messagePattern, params)
> try
> {
> operation()
> }
> finally
> {
> NDC.pop()
> }
> }
>
> withNdc("Parameter is {}", ["bar"])
> {
> // NDC has the message "Parameter is bar." pushed. In case of
> Logback, I would postpone the actual formatting until the formatted
> message is really needed/used by an appender (like in LoggingEvent)...
> }
> // NDC has been popped.
> ====================================
>
> which would mean automatic NDC cleanup. Beside Groovy which is
> gaining quite some momentum at the moment, Java will - probably -
> also get them. See http://www.javac.info/
>
> To me, NDC and MDC are completely different things. While the MDC
> gives informations about certain states of the application like the
> user that is executing the code, the NDC is more like a manual
> StackTrace, adding stacked state informations about the context. The
> feature of nesting would be hard to implement using MDC, e.g. in
> case of recursion.
>
> While I *can* live without an NDC I would definitely use it if it
> was available in SLF4J.
> I missed out on both MDC and NDC because I previously used
> commons.logging but now, with SLF4J, I'm using MDC all the time. It
> was just harder or, let's say, impossible from the maintainability
> perspective, to log the same infos that I now obtain using the MDC.
>
> Beside that, it seems that the absence of NDC in SLF4J/Logback is a
> pain-point for some people that would like to switch over from log4j
> to slf4j/logback. I found http://www.flester.com/blog/2008/02/03/slf4j-log4j-and-ndc
> when I was searching for a reason why there's no NDC. Yes, I've
> seen that you know the link ;)
>
> In contrast to log4j, I would suggest that peek should be left out
> to prevent misuse of the NDC in application logic. While it would
> still be possible using the cloneStack method it's way more obvious
> that this would be a bad idea, imo.
> Additionally, I'd suggest to implement message formatting like in
> the log statements because I guess that NDC could be disabled
> globally by configuration to save memory and have the ability to
> achieve better performance on demand.
>
> I think it would be relatively easy to implement an SLF4J NDC in a
> similar way like MDC.
> What do you think about that?
>
> Regards, Joern.
>
> On 22.01.2009, at 12:04, Ceki Gulcu wrote:
>
>>
>> Hi Joern,
>>
>> You are not beating a dead horse. There is no NDC in SLF4J because
>> it is thought that the MDC offers a better more general solution
>> than the NDC.
>>
>> However, I don't understand what you mean when you write:
>> slf4j.NDC("Parameter is {}.", obj)
>>
>> What does the NDC offer that the MDC does not? I mean from a users
>> point of view.
>>
>> Cheers,
>>
>> Joern Huxhorn wrote:
>>> Hi.
>>> I hope I'm not beating a dead horse but I just somewhat
>>> rediscovered the log4j NDC class (I was using commons.logging
>>> before switching to slf4j) and I was wondering why there is no NDC
>>> class defined in slf4j.
>>> While the original NDC class could be improved it seems like a
>>> quite nice addition to the MDC. I guess it would get especially
>>> interesting with closures where you could write something like
>>> (pseudo-code)
>>> slf4j.NDC("Parameter is {}.", obj)
>>> {
>>> [the nested code]
>>> }
>>> which would remove the necessity to pop the stack manually.
>>> But even without closures an NDC implementation utilizing
>>> parameters seems really worthwhile to me.
>>> Just wondering,
>>> Joern.
>>
>>
>> --
>> Ceki Gülcü
>> Logback: The reliable, generic, fast and flexible logging framework
>> for Java.
>> http://logback.qos.ch
>> _______________________________________________
>> user mailing list
>> user at slf4j.org
>> http://www.slf4j.org/mailman/listinfo/user
>
More information about the slf4j-user
mailing list