10 Replies Latest reply on Mar 26, 2013 12:28 PM by jamezp

    EAP 6.1.0 Alpha: Using logging in a shared module

    jrantav

      We are having difficulties to implement logging separation with JBoss EAP 6.1 Alpha when using shared modules containing common libraries. In our scenario we have installed several shared libraries (Spring, Dozer, Logback, shared custom logic etc) as JBoss module(s) and deploying our business services as war packaged applications. War applications are using the common classes from the module libraries.

       

      One of our requirements is that each web application should have its own logging context (logfiles, levels, log configurations etc). We have tried to follow instructions described in Logback manual (http://logback.qos.ch/manual/loggingSeparation.html) and introduced ContextJNDISelector and SiftingAppenders etc. Both applications have their own logback.xml files which are read and logback is initialized during the application deployment.

       

      However it seems that when applications are using shared module containing logging classes, they eventually share the same classloader responsible of maintaining at least some of the logging instances (e.g. static reference to logger classes). So far we have noticed that if we deploy webapp_A and webapp_B using the same module, at least logging configurations will affect to each other (for example if we change A’s root logger level to INFO, it will affect to webapp_B also).

       

      We suspect that this is because classloader is shared, but has anybody else solved this kind of problem? Or is there any way to enable each webapp to have own classloader instance of the libraries in module?

       

      We have considered other logging frameworks, too, but it would seem that our usage scenario just doesn't work with JBoss modules approach. We're currently testing if the same app works as-is with Tomcat, as we're suspecting this is JBoss modules issue.

       

      Just to confirm that it isn't about our code, we've tested with starwars reference app (https://github.com/ceki/logback-starwars) and are seeing the same problems in there too.

       

      EDIT: we can reproduce the problem with Tomcat global classpath so JBoss modules is not to blame here. So is it fundamentally so that existing logging frameworks have to be packaged with the application?

        • 1. Re: EAP 6.1.0 Alpha: Using logging as shared module
          jamezp

          We are having difficulties to implement logging separation with JBoss EAP 6.1 Alpha when using shared modules containing common libraries. In our scenario we have installed several shared libraries (Spring, Dozer, Logback, shared custom logic etc) as JBoss module(s) and deploying our business services as war packaged applications. War applications are using the common classes from the module libraries.

           

          One of our requirements is that each web application should have its own logging context (logfiles, levels, log configurations etc). We have tried to follow instructions described in Logback manual (http://logback.qos.ch/manual/loggingSeparation.html) and introduced ContextJNDISelector and SiftingAppenders etc. Both applications have their own logback.xml files which are read and logback is initialized during the application deployment.

           

           

          What you're attempting to do won't really work. You can log each deployments log messages separately, but shared libraries will likely be configured based on the system log context. I don't see a way this could work in any log manager with shared dependencies.

           

          We suspect that this is because classloader is shared, but has anybody else solved this kind of problem? Or is there any way to enable each webapp to have own classloader instance of the libraries in module?

          You're correct it's because each module has it's own class loader.

           

          The only way to get this to work exactly how you want would be to included the dependencies with each deployment. If you did that you could use logging profiles in the logging subsystem for each deployment to keep everything separate and allow runtime configuration changes.

           

          We have considered other logging frameworks, too, but it would seem that our usage scenario just doesn't work with JBoss modules approach. We're currently testing if the same app works as-is with Tomcat, as we're suspecting this is JBoss modules issue.

           

          Just to confirm that it isn't about our code, we've tested with starwars reference app (https://github.com/ceki/logback-starwars) and are seeing the same problems in there too.

           

          EDIT: we can reproduce the problem with Tomcat global classpath so JBoss modules is not to blame here. So is it fundamentally so that existing logging frameworks have to be packaged with the application?

           

           

          Bundling the logging framework wouldn't solve this problem. The common libraries (modules) would still use their own class loader.

           

          --

          James R. Perkins

          • 2. Re: EAP 6.1.0 Alpha: Using logging as shared module
            jrantav

            Ok. I read this so that logging from any shared library is not really possible in a way that it would fully work having app-specific logging contexts. I think this is a big pitfall with using shared libraries, and certainly a drawback to our planned shared library usage.

             

            It would also mean that examples like https://github.com/ceki/logback-starwars cannot fundamentally work, anywhere.

            You can log each deployments log messages separately, but shared libraries will likely be configured based on the system log context. I don't see a way this could work in any log manager with shared dependencies.

             

            It actually seems shared libraries are configured based on the app that gets to initialize them first, so there's a race there.

            • 3. Re: EAP 6.1.0 Alpha: Using logging as shared module
              jaikiran

              James Perkins wrote:

               

              We are having difficulties to implement logging separation with JBoss EAP 6.1 Alpha when using shared modules containing common libraries. In our scenario we have installed several shared libraries (Spring, Dozer, Logback, shared custom logic etc) as JBoss module(s) and deploying our business services as war packaged applications. War applications are using the common classes from the module libraries.

               

              One of our requirements is that each web application should have its own logging context (logfiles, levels, log configurations etc). We have tried to follow instructions described in Logback manual (http://logback.qos.ch/manual/loggingSeparation.html) and introduced ContextJNDISelector and SiftingAppenders etc. Both applications have their own logback.xml files which are read and logback is initialized during the application deployment.

               

               

              What you're attempting to do won't really work. You can log each deployments log messages separately, but shared libraries will likely be configured based on the system log context. I don't see a way this could work in any log manager with shared dependencies.

               

              I haven't had a look at the context selector pluggability in JBoss Logging. But if there was way to plugin a "foo" context selector which would return a logging context based on the "current deployment" instead of relying on the "current deployment classloader" then I guess each deployment could have a unique context even if they share a common JBoss module (since we no longer rely on classloaders). I don't know if this is possible in practice.

              • 4. Re: EAP 6.1.0 Alpha: Using logging as shared module
                jrantav

                jaikiran pai wrote:


                I haven't had a look at the context selector pluggability in JBoss Logging. But if there was way to plugin a "foo" context selector which would return a logging context based on the "current deployment" instead of relying on the "current deployment classloader" then I guess each deployment could have a unique context even if they share a common JBoss module (since we no longer rely on classloaders). I don't know if this is possible in practice.

                As far as I know, this might be possible if there wouldn't be statically defined loggers ("final static Logger logger = LoggerFactory.getLogger(MyClass.class);").

                 

                From slf4j FAQ about static loggers:

                 

                For libraries shared between applications, not possible to take advantage of repository selectors. It should be noted that if the SLF4J binding and the underlying API ships with each application (not shared between applications), then each application will still have its own logging environment.

                 

                There's also some enlightning speculation about this in commons logging wiki. Quote:

                 

                The real root cause of this problem is that SHARED data (static members on a class) is being shared across supposedly independent "applications". If no classes are "shared" between applications then the problem does not exist. However it appears that (to my personal frustration) container vendors continue to encourage the use of shared classes, and application developers continue to use it.

                The alternative solution is: avoid the use of "static" references to Log objects in any code that might be deployed into a shared classpath.

                 

                Some libraries use static loggers, some not. It would seem that for those using static there is no hope. For the ones that don't there's some possibility of something.

                • 5. Re: EAP 6.1.0 Alpha: Using logging as shared module
                  jamezp

                  Yeah, that's what I meant. It should be configured based the first application that creates the static logger, not the system log context. Sorry about that. It's definitely not a race condition.

                   

                  --

                  James R. Perkins

                  • 6. Re: EAP 6.1.0 Alpha: Using logging as shared module
                    jamezp

                    It's not really possible to do that. Static loggers are common and frankly encouraged. Things like JSF use static loggers therefore using a module based context selector won't work. Well in theory it could, but you're going to end up with a bunch of exception modules to list for each server module provided.

                     

                    As your second quote indicates it's a shared module problem. If shared resources need to be logged/configured separately they can't be shared and they need to be included with each deployment separately. It's the only way to do it.

                     

                    Really what needs to happen is that the shared modules would need a new/different class loader for each deployment they're dependent on. There is no real way to do that currently and it would likely be ugly to get that to work.

                     

                    --

                    James R. Perkins

                    • 7. Re: EAP 6.1.0 Alpha: Using logging as shared module
                      jrantav

                      James Perkins wrote:


                      Static loggers are common and frankly encouraged.

                       

                      Yes, it seems that even some of the libraries that are distributed in EAP/AS downloads have static loggers. If JBoss modules is recommended, shouldn't at least the modules that are being distributed with the server get rid of static loggers?

                       

                      Based on the information available, I don't think static loggers should really be used for code that could be shared among multiple application contexts. With dropping the static modifier, things seem to be working fine.

                       

                      Though I understand that that could be considered just hiding the real problem. Modules distributed with JBoss rarely are all that is needed, and chances are that anyone depending on module architecture anyway has a need for a library that has static loggers. But I would expect still at least the distribution to behave well, anyway.

                      • 8. Re: EAP 6.1.0 Alpha: Using logging as shared module
                        jaikiran

                        I hadn't taken into account static references to loggers in various classes, when I replied earlier. I do understand what you both mean. However, I still think this might be possible to be achieved from within the logging framework itself, but maybe it will add some overhead. So when some client code does a :

                         

                        private static final Logger logger = Logger.getLogger(MyClass.class); // the most common way of getting the logger
                        

                         

                        I think the logging library could return a stub/proxy (call it whatever). This returned instance would then be smart enough to look for the "right deployment context" (using some kind of context selector) when subsequently the client code does any operation on that returned logger instance. This is all theory though, I haven't looked into any logging libraries in detail to see if this makes sense and if it's feasible without adding too much performance overhead.

                        • 9. Re: EAP 6.1.0 Alpha: Using logging as shared module
                          jamezp

                          It would be nearly impossible to get rid of all the static loggers. We would have to rewrite JSF and probably several other libraries, so it's very unlikely that would ever happen :-)

                           

                          Static loggers are common and suggested because in most cases they should be static. It can be a real performance hit to use Logger.getLogger() frequently.

                           

                          Any shared class loader is going to have this problem. The only way to get this to work would be to include the libraries in each deployment. Then the class loader won't be shared.

                           

                          --

                          James R. Perkins

                          • 10. Re: EAP 6.1.0 Alpha: Using logging as shared module
                            jamezp

                            jaikiran pai wrote:

                             

                            I hadn't taken into account static references to loggers in various classes, when I replied earlier. I do understand what you both mean. However, I still think this might be possible to be achieved from within the logging framework itself, but maybe it will add some overhead. So when some client code does a :

                             

                            private static final Logger logger = Logger.getLogger(MyClass.class); // the most common way of getting the logger
                            

                             

                            I think the logging library could return a stub/proxy (call it whatever). This returned instance would then be smart enough to look for the "right deployment context" (using some kind of context selector) when subsequently the client code does any operation on that returned logger instance. This is all theory though, I haven't looked into any logging libraries in detail to see if this makes sense and if it's feasible without adding too much performance overhead.

                             

                            I'm not sure that would work. The basic concept is around a LogContext. A LogContext holds the configuration, loggers, handlers, etc. Then there is a LogContextSelector that selects the LogContext, in our case based on the class loader with some filtering.

                             

                            To use a proxy a logger would have to be aware of loggers or handlers on a different LogContext. I can't think of a good way to do this. I don't think we want different log contexts being aware of each other.

                             

                            --

                            James R. Perkins