[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