[Bug 84] New: LoggerContextFilter is useless (org.slf4j.Loggerfactory bug ++)

http://bugzilla.qos.ch/show_bug.cgi?id=84 Summary: LoggerContextFilter is useless (org.slf4j.Loggerfactory bug ++) Product: logback-core Version: unspecified Platform: All OS/Version: All Status: NEW Severity: normal Priority: P1 Component: Other AssignedTo: logback-dev@qos.ch ReportedBy: jel@linofee.org Since LoggerFactory obtains the LoggerContext to use in its static init stage, using a LoggerContextFilter as described in Chapter 8 is completely useless, since the JNDI selector is never consulted again. Digging deeper on that issue reveals, that using a ContextJNDISelector (even if it would work) rarely leads to the intended behavior (e.g. webapp related logging), and is probably not thread safe wrt. common practice and intended logging. E.g. in tomcat we have two different cases: a) each webapp provides its own slfj4*.jar as well as *logback*.jar b) slfj4*.jar as well as *logback*.jar are shared via tomcat/common/lib or tomcat/share/lib c) a und b mixed Well, to get things right, one can say case c) is unsupported ;-). In case a) logback has its own playground, so using JNDI doesn't make sense at all, since the webapp/logback has its own playground - doesn't interfere with other web apps since loaded via its dedicated classloader. However case b) is a little bit more challenging. Here the LoggerFactory and other classes are !shared! between several webapps, since loading is delegated from the dedicated webapp classloader to the shared webapp classloader, which picks up everything in share/lib , common/lib. So right now in 0.9.7, even if one uses JNDISelector a per webapp logging is impossible: The first webapp, which asks for a LoggerFactory always wins! All other webapps, which ask later for a LoggerFactory.getLogger() will get a Logger from the LoggerContext associated with the first webapp, since the context is "cached", i.e. the JNDI selector gets never consulted again. Assuming the LoggerFactory problem gets fixed by using e.g. public static Logger getLogger(* *) { return StaticLoggerBinder.SINGLETON.getLoggerFactory().getLogger(**); } there is still a problem wrt. common practice aka log* usage pattern and webapp shared classes, which can not be resolved by JNDI: Today most developer use something like: public class XY { private static [final] Logger log = LoggerFactory.getLogger(XY.class); ... } That implies the same problem, as with the current LoggerFactory bug: The class gets the Logger from the context associated with the first webapp, which needs the shared class. And that's why all other webapps, which later need this class will use the the logger context of the first webapp. So e.g. if webapp A is configured to log to /var/log/a.log and another webapp B is configured to log to /var/log/b.log the loging output of shared classes will always go to /var/log/a.log if webapp used the classes in question first, no matter on which thread aka in which webapp the shared classes are used. So even if LoggerFactory gets fixed, JNDI selector is of little use, if one wants to have a webapp dedicated log as soon as shared classes are involved. The only way to solve the didcated webapp log problem a can think of, to introduce another level of indirection in the Logger.log* etc. method, which takes care of thread local settings and the settings of its parent threads (e.g. an application may start other threads, which do not inherit the thread local settings from the current thread ...). But this would probably influence the performance of logback in a rather negative way. Another idea might be an architecture re-design: sharing Loggers would be no problem because of thread local AppenderContext soft ref, which points to an Appender in the global AppenderStore singleton ... RFE: These problems should be reflected chapter 8 of the logback manual to avoid further confusion ... -- Configure bugmail: http://bugzilla.qos.ch/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are the assignee for the bug, or are watching the assignee.

http://bugzilla.qos.ch/show_bug.cgi?id=84 ------- Comment #1 from lars@koedderitzsch.net 2007-09-18 08:04 ------- Excellent analysis, I am hitting the exact same problems as the original reporter. Logback isn't ready for serious enterprise development because of the mentioned problems. My case a bit different from the ones depicted originally: b) sl4j*.jar, logback*.jar are sitting in the .ear file, the EAR contains multiple webapps (.war). Each of this webapps should log into its own context. However, because of libraries (Spring, Jakarta Commons and many more) also being shared in the ear this is impossible, because once Logger instances in the shared libs are created the initializing logger context has won. On a sidenote: Log4j has exactly the same problem, there it is the LoggerRepository which is fixed once the Logger instances are created. As I understand the Logback project wants to rise above the (for compatibility reasons) rather static Log4j. I think this would be an excellent topic for actually improving Logback over other log solutions. That being said I am quite astonished that there hasn't been a reaction from the devs on this well reasoned bug report. -- Configure bugmail: http://bugzilla.qos.ch/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are the assignee for the bug, or are watching the assignee.

http://bugzilla.qos.ch/show_bug.cgi?id=84 ------- Comment #2 from noreply.ceki@qos.ch 2007-09-18 22:33 ------- Hello Jens, Lars, I am confused about this report. We have tested ContextJNDISelector and it works as it is supposed to. Although there are cases where ContextJNDISelector does not work, I believe that ContextJNDISelector works, assuming: 1) logger fields (in shared libraries!) are *not* static 2) logback-core.jar and logback-classic.jar are in tomcat/common/lib in tomcat (or in a directory on the common class path in other containers) In case 1) is not true, then the logger context of first web-app will win (but only for that logger field and shared library) Moreover, as you describe in your report, when each web-app provides its own copy of logback*.jar, then you have separation by virtue of class loader separation in each web-app (assuming local-first delegation model as in Tomcat). I mean no offense but have you read the context selector docs? http://logback.qos.ch/manual/contextSelector.html As for the separation problem in EAR files, again you need to remove logback-*.jar from the EAR and place them higher up the container class loader hierarchy. Admittedly, I have not tested logging separation in EJBs. I am unsure about how to specify the name of the context for each EJB. If you can pass parameters for the EJB as in web.xml, then that is the way to go. Is this any clearer? -- Configure bugmail: http://bugzilla.qos.ch/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are the assignee for the bug, or are watching the assignee.

http://bugzilla.qos.ch/show_bug.cgi?id=84 ------- Comment #3 from lars@koedderitzsch.net 2007-09-18 22:50 ------- Hello Ceki, thanks for your response. As Jens already pointed out the most common pattern to logging (even in common libaries as Jakarta Commons, Spring whatsoever) is using a static logger, eg. public class XY { private static [final] Logger log = LoggerFactory.getLogger(XY.class); ... } If such libraries are shared (either by being in tomcats shared libs, or by being directly in the ear) by multiple webapps, the logger context wins in which the original loading of the logging class (aka XY, see above) happens. To make an example. An ear contains two webapplications A and B, both have different logger context CtxA and CtxB. A library (say Spring for instance) is place in the ear and both webapps reference the library through their MANIFEST.MF. On application startup webapp A gets initialized first, during initialisation the classes of the shared libary (Spring) are loaded, therefor static loggers initialized with the context CtxA. Now webapp B gets initialized, classes of the shared libary are already loaded by the EARClassloader, the loggers continue to use CtxA. At runtime regardless of wich logger context will be set by context selectors of the webapps, all logging done by the shared classes will always go to CtxA. One can argue that common libaries should not use static loggers, but always obtain loggers freshly from the LoggerFactory. But that is a pipe dream, because the de-facto pattern in obtaining and using a logger is through a static field as depicted above. To achieve true per-webapp logging, already initialized loggers need to be able to switch logger contexts, for instance through TreadLocal or other mechanisms. -- Configure bugmail: http://bugzilla.qos.ch/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are the assignee for the bug, or are watching the assignee.
participants (1)
-
bugzilla-daemon@pixie.qos.ch