[slf4j-user] Per-web-app logging with jars on the server's classpath

Jacob Kjome hoju at visi.com
Wed Mar 14 03:33:40 CET 2007


Your repository selector is based on classloader, right?  Doesn't 
JBoss use a "Unified Classloader" strategy?  That is, every app 
running on the server uses the same classloader?  That is, unless it 
is configured otherwise.  If this is truly the case, then you 
repository selector will not separate logger repositories under 
JBoss.  And I strongly recommend you avoid Classloader-based 
repository selectors.  You'd be better off using a JNDI-based 
repository selector.  If you use Log4j 1.3, one is already available 
[1].  If not, you can grab the one from the sandbox [2].  Note that a 
Classloader-based version exists there, but you should ignore that 
and look at the ContextJNDISelector.  Can you try this out and see if 
it works for you?

[1] 
http://logging.apache.org/log4j/docs/api-1.3/org/apache/log4j/selector/ContextJNDISelector.html
[2] 
http://svn.apache.org/viewvc/logging/sandbox/log4j/log4j_sandbox/tags/LOG4J_SANDBOX_ALPHA3/src/java/org/apache/log4j/selector/


Jake

At 05:15 AM 3/13/2007, you wrote:
 >Jacob Kjome <hoju <at> visi.com> writes:
 >
 >>
 >>
 >> It doesn't much matter what the config file looks like, but what your
 >> custom repository selector is doing.  Clearly it isn't working,
 >> otherwise you'd have separate logger repositories and no cross-talk
 >> between application-specific logger repositories.  So, what does your
 >> implementation look like?  How it the repository selector
 >> installed?.  How are you configuring each repository?  Where are your
 >> config files?  Where's Log4j?
 >>
 >> Jake
 >>
 >> At 06:59 PM 3/12/2007, you wrote:
 >>  >We have a custom web framework packaged into a jar file
 >> (myframework.jar) that
 >>  >is used by 50 web applications deployed as WAR files on Weblogic 8.1 SP4.
 >>  >myframework.jar uses the Spring framework internally (which uses commons
 >>  >logging API), so we must continue to use SLF4J's
 >jcl104-over-slf4j-1.3.0.jar
 >>  >for the foreseeable future.  None of these web apps use EJBs 
and I want to
 >>  >avoid them.
 >>  >
 >>  >myframework.jar, log4j.jar, slf4j*.jar spring.jar, and dozens 
of other 3rd
 >>  >party dependencies are loaded on Weblogic's server classpath.
 >>  >myframework.jar is under continual development by my team and we can't
 >>  >redeploy every WAR file with the new version of libraries in 
WEB-INF/lib -
 >>  >so we have to load myframework and other JARs on weblogic's classpath.
 >>  >Each web app has very few Java classes of its own - most are
 >Spring-injected
 >>  >from myframework.jar.
 >>  >
 >>  >This has proven to be an interesting puzzle because we want 
each web app to
 >>  >write to its own log file (appA.log, appB.log, etc), but be 
able to record
 >>  >log entries from classes inside myframework.jar, spring.jar, etc for
 >>  >debugging purposes.
 >>  >
 >>  >I bought the Log4J book, read Chapter 8, and followed the JBoss
 >instructions
 >>  >here http://wiki.jboss.org/wiki/Wiki.jsp?page=Log4jRepositorySelector
 >>  >to create a custom RepositorySelector (which loads
 >> /WEB-INF/log4j.properties),
 >>  >and modified myframework's StartupListener to initialize this
 >>  >RepositorySelector in each web app's web.xml.
 >>  >
 >>  >The problem is that when I start weblogic with several webapps (appA.war,
 >>  >appB.war, appC.war, etc), all log entries are written to appA.log, even
 >>  >though each application has its own WEB-INF/log4j.properties (albeit they
 >>  >are currently all the same, except for the
 >"log4j.appender.file.File" value).
 >>  >
 >>  >Am I doing something wrong to keep JAR files at the server level but let
 >>  >each web app write to its own log file?  Thank you
 >>  >
 >>  >Here is appA's log4j.properties file:
 >>  >log4j.rootLogger=warn, file
 >>  >
 >>  >### direct messages to file <app name>.log ###
 >>  >log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
 >>  >log4j.appender.file.DatePattern='.'yyyy-MM-dd
 >>  >#Each app should go to its own log file but they are not
 >>  >log4j.appender.file.File=c:/logs/appA.log
 >>  >log4j.appender.file.layout=org.apache.log4j.PatternLayout
 >>  >log4j.appender.file.layout.ConversionPattern=%d{dd MMM yyyy HH:mm:ss,SSS}
 >>  >%5p %C{1} - %m%n
 >>  >
 >>  >log4j.logger.org.apache.struts=error
 >>  >log4j.logger.org.apache.commons=error
 >>  >log4j.logger.org.apache.jcs=error
 >>  >log4j.logger.org.springframework=error
 >>  >log4j.logger.org.hibernate=error
 >>  >log4j.logger.org.acegisecurity=error
 >>  >
 >>  >#Make sure you turn logging off before deploying to staging or 
production.
 >>  >log4j.logger.com.myframework.core=debug
 >>  >
 >>  >_______________________________________________
 >>  >user mailing list
 >>  >user <at> slf4j.org
 >>  >http://www.slf4j.org/mailman/listinfo/user
 >>
 >
 >
 >public class JbossAppRepositorySelector implements RepositorySelector {
 >       private static boolean initialized = false;
 >       private static Object guard = LogManager.getRootLogger();
 >       private static Map repositories = new HashMap();
 >       private static LoggerRepository defaultRepository;
 >
 >       public static synchronized void init(ServletConfig servletConfig)
 >       throws ServletException {
 >               init(servletConfig.getServletContext());
 >       }
 >
 >       public static synchronized void init(ServletContext servletContext)
 >       throws ServletException {
 >               if (!initialized) // set the global RepositorySelector
 >               {
 >                       defaultRepository = LogManager.getLoggerRepository();
 >                       RepositorySelector theSelector = new 
JbossAppRepositorySelector();
 >                       LogManager.setRepositorySelector(theSelector, guard);
 >                       initialized = true;
 >               }
 >
 >               Hierarchy hierarchy = new Hierarchy(new 
RootCategory(Level.DEBUG));
 >               loadLog4JConfig(servletContext, hierarchy);
 >               ClassLoader loader = 
Thread.currentThread().getContextClassLoader();
 >               repositories.put(loader, hierarchy);
 >       }
 >
 >       public static synchronized void removeFromRepository() {
 > 
repositories.remove(Thread.currentThread().getContextClassLoader());
 >       }
 >
 >       // load log4j.xml from WEB-INF
 >       private static void loadLog4JConfig(ServletContext servletContext,
 >               Hierarchy hierarchy) throws ServletException {
 >               String log4jFile = null;
 >               InputStream log4JConfig = null;
 >               Properties properties = new Properties();
 >               PropertyConfigurator conf = new PropertyConfigurator();
 >               try {
 >                       log4jFile = "/WEB-INF/log4j_webapp.properties";
 >                       log4JConfig = 
servletContext.getResourceAsStream(log4jFile);
 >                       properties.load(log4JConfig);
 >                       conf.doConfigure(properties, hierarchy);
 >               } catch (Exception e) {
 >                       throw new ServletException(e);
 >               }
 >       }
 >
 >       private JbossAppRepositorySelector() {
 >       }
 >
 >       public LoggerRepository getLoggerRepository() {
 >               ClassLoader loader = 
Thread.currentThread().getContextClassLoader();
 >               LoggerRepository repository = (LoggerRepository) 
repositories.get(loader);
 >               if (repository == null) {
 >                       return defaultRepository;
 >               } else {
 >                       return repository;
 >               }
 >       }
 >}
 >
 >
 >com.myframework.web.StartupListener:
 >public void contextInitialized(ServletContextEvent event) {
 >       ...
 >       JbossAppRepositorySelector.init(event.getServletContext());
 >       ...
 >}
 >
 >_______________________________________________
 >user mailing list
 >user at slf4j.org
 >http://www.slf4j.org/mailman/listinfo/user




More information about the slf4j-user mailing list