
Hello everybody. On 06.03.2010, at 18:13, Ceki Gülcü wrote:
On 06/03/2010 4:29 PM, Joern Huxhorn wrote:
On 06.03.2010, at 14:48, Ceki Gülcü wrote:
Hello all,
Here are the 4 items I'd like to address in SLF4J 2.0:
1) Varargs for Logger methods http://bugzilla.slf4j.org/show_bug.cgi?id=31 Require JDK 1.5 and remain binary compatible as explained in my comment #31 dated 2009-03-25
2) logging exception if last argument, as exaplined by Joern in http://bugzilla.slf4j.org/show_bug.cgi?id=43
3) Avoid bogus incompatibility warnings http://bugzilla.slf4j.org/show_bug.cgi?id=154
4) fix http://bugzilla.slf4j.org/show_bug.cgi?id=170 possibly with a nop implementation of org.apache.log4j.NDC
Are there any other major items? Is everyone OK with requiring JDK 1.5 in SLF4J 2.0?
Hi Ceki,
While I'm a big fan of #31 and #43 and personally don't need <1.5 compatibility, I fear that dropping it might seriously hurt libraries using it right now.
That's the $64k question. If library lA depends on SLF4J and target JDK 1.4, nothing prevents lA from continuing to use SLF4J version 1.5.11. It gets a little trickier when library lB targets JDK 1.5 and depended on SLF4J v2 and if some application aX requires both lA and lB. Since SLF4J v2 is intended to be binary compatible with SLF4J 1.5.x, aX can use SLF4J v2 and lA will run just fine (without recompilation or anything). Where it gets really hairy is when an app server like Geronimo, JBoss or Spring DM bundle some version of SLF4J, say v1.5.11. If the end-user cannot freely chose the version of SLF4J (and this happens quite frequently) because the the app server imposes its version of SLF4J, then we might run into serious problems, unless SLF4J v2 and 1.5.x are binary compatible.
As mentioned in comment #10 dated 2007-10-10 on bug 31, we can have binary compatibility as long as
logger.trace|debug|info|warn|error(String, Object[]) logger.trace|debug|info|warn|error(Marker, String, Object[])
are changed to
logger.trace|debug|info|warn|error(String, Object...) logger.trace|debug|info|warn|error(Marker, String, Object...)
with all the other methods remaining unchanged.
That's not entirely true. As you stated in that comment, compatibility is not the case if someone compiles against SLF4J v2 (with varargs) but the container uses JDK 1.4. http://bugzilla.slf4j.org/show_bug.cgi?id=31#c75 I fear that SLF4J v2 might sneak up on some people by either not RTFM of SLF4J v2 or by some dependency where the developers did not RTFM the SLF4J v2 manual. It wouldn't be our fault in both cases but it would boil down to "Updating xyz broke my build" subjects in mailinglists with the explanation that it was because of the SLF4J dependency.
If the assumption about binary compatibility is wrong, SLF4J will probably not survive the shitstorm ensuing the release of v2.
I also guess that lots of people using SLF4J aren't following this mailinglist so this should probably also be discussed on slf4j-user@qos.ch . We'd still miss lots of users and I guess this will result in crying after the fact.
True. As Gunnar Wagenknecht observed, the BasicMDCAdapter class since it was introduced in early 2008, withing its remove() method invokes a method new to JDK 1.5. Thus, whenever the MDC.remove method is called under JDK 1.4, for any binding other than logback (which has its own MDCAdapter implementation and anyhow requires JDK 1.5) will cause an exception to be thrown. As far as I can remember no one has complained about this bug before Gunnar. So either no one is using org.slf4j.MDC#remove under JDK 1.4 or those who do, do not care enough to complain. Here is the link to BasicMDCAdapter dating from 2008-01-15: http://tinyurl.com/yherxp9
I find this BasicMDCAdapter.remove episode really puzzling. The only simple explanation I see is that few SLF4J users run under JDK 1.4 or more accurately the overlap of org.slf4j.MDC and JDK 1.4 use corresponds to a very small number of users.
You're right. But there's also the possibility that people are only putting values into MDC without ever removing them again, overwriting them instead. Before I switched all my stuff to SLF4J I was using commons-logging. This was the case for all the projects I was involved in. CL did not support MDC and I think that this is one of the reasons why MDC is - even now - quite underused. Lots of people switched their codebase over to SLF4J by a simple search & destroy, I guess.
It's a shame that there's no tool to analyze the whole central Maven2 repository concerning this, or is there? It would be great if there was a way to find out which modules depend on SLF4J (either directly or transitively) and are still 1.4.
Let's google it. :-)
Did you succeed?
If we'd consider my alternative suggestion in http://bugzilla.slf4j.org/show_bug.cgi?id=31 , i.e. http://github.com/huxi/slf4j/tree/slf4j-redesign , we'd stay binary compatible, keep JDK<1.5 support and would still support 1) and 2) - it's a win-win.
If we are going to re-implement org.slf4j.Logger under org.slf4j.n.Logger, we might as well call it org.newslf4j.Logger and start over from scratch. Copying the API to new packages avoids conflicts but otherwise constitutes a radical break.
Yes, it does. But it also cleans up the API and adds some very substantial features. There are lots of methods that aren't necessary anymore with varargs and exception support built in. Additional ones would be extremely nice to have. Methods supporting the (or a) Message interface would enable the user to define his own application-specific message implementation which would bring a whole new level to the framework. He could access those special messages without parsing in specifically written appenders. I've also added log(Level,....) and isEnabled(Level[,Marker])-methods for cases where the actual level a call uses is determined programmatically. This is something that we needed on several occasions, too. But additional methods can't be added to the original SLF4J because, as you correctly enforce, SLF4J API is frozen and must stay that way. What I suggest is a bit like the junit package switch. With JUnit 4 the package changed from junit to org.junit. The original junit keeps working as before but new stuff was added in org.junit. You are right: the package could be named anything. The only reasons I choose org.slf4j.n was a) making a switch easy by just adding .n to import statements b) using the SLF4J brand because it's established and people already believe/put trust in it c) it was merely a suggestion The main point, though, is, that there would be zero impact on any existing code base. Everything, even SLF4J implementations, don't have to do anything. The new API would be supported anyway. In case of JDK>=1.5 implementations like Logback, it does make a lot of sense to implement the new API directly (so the Message reaches the appenders - instead of an String) and wrapping the other way around, i.e. using a wrapper to support the original SLF4J API (which is already provided in the new Logger interface via getOldLogger() method). But this isn't required for org.slf4j.n to work.
Concerning 4), I've also implemented an NDC in my branch which uses the same Message (and, therefore, cheap, parameterized messages like SLF4J) as my suggested Logger interface. This means it's much more powerful than the log4j one (which expects one word per entry without enforcing it - I derive this from the way NDC is formatted in log4j xml) but log4j NDC can be implemented easily by wrapping it. It would only be available in the new SLF4J API - that was my plan, at least. In case of log4j-over-slf4j, we could use the new SLF4J NDC if available (i.e. in case of Java 1.5), falling back to an NOP implementation otherwise.
As I stated before, I'm a big fan of NDC and see it as a very good supplement to MDC. We actually use the NDC version available in Lilith in our production environment and it's quite helpful. I really don't understand why it was omitted from SLF4J. It's comparable to a manual, semantic stacktrace.
If you are used to log4j's NDC, having NDC in SLF4J is more comfortable than not having it. Otherwise, since MDC is semantically richer than NDC (one can trivially implement NDC over MDC), one can always get by using MDC instead of NDC. Another reason was that by scrapping NDC in SLF4J there was one less piece of code to maintain.
True, but that way the NDC kind of "pollutes" the MDC. Also, an NDC implementation is quite trivial. The one I provided in the prototype handles the same Messages (incl. the same parameterized message format as a shortcut) as logging - with the same positive aspects concerning performance, i.e. the formatted message is only actually created if it is requested, not while something is put on the NDC. If the NDC is ignored by appenders, it won't be formatted, ever. In case of MDC the formatting would always need to be performed. We'd use it for trace-like stuff, e.g. putting "Inside method xyz with arguments {}, {}, {}" on the NDC. In that case, my suggested NDC would make a significant difference, especially if it's actually ignored. Cheers, Joern.