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 hear that you when you sat that you would like to see NDC introduced in SLF4J
but I still don't really see the added value of NDC when MDC is avaliable.
The blog about NDC by "mike" does not really explain why NDC is better. It
explains that the NDC API is different and that his team would like to stay with
an API they already use, namely NDC.
As for your examples with closures, other than showing that closures are cool,
they do not explain why NDC is required when MDC is available. Can you think of
an explanation without closures demonstrating the advantages of NDC?
> While I *can* live without an NDC I would definitely use it if it was
> available in SLF4J.
I am interested. How you would use NDC more efficiently than MDC, if NDC was
available in SLF4J?
Cheers,
[1] http://www.flester.com/blog/2008/02/03/slf4j-log4j-and-ndc
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
[email protected]
http://www.slf4j.org/mailman/listinfo/user
_______________________________________________
user mailing list
[email protected]
http://www.slf4j.org/mailman/listinfo/user
--
Ceki Gülcü
Logback: The reliable, generic, fast and flexible logging framework for Java.
http://logback.qos.ch
_______________________________________________
user mailing list
[email protected]
http://www.slf4j.org/mailman/listinfo/user