views:

179

answers:

1

Is it possible to use a single log4j jar file in an tomcat 5.5 setup, where it can be used by multiple webapps and have seperate logging for each webapp?

I have about 8 different webapps written where the only real difference between the log4j property files is the log filename. However if I attempt to move log4j from the webapp WEB-INF/lib directory to the tomcat5 shared/lib directory I run into problems.

All the property files basically look the same as the one below, where I just set file.name using System.setProperty("file.name", ) in the code. Not necessary really, but I was toying with the idea of using a single properties file for all components.

log4j.rootLogger=DEBUG, LogFile
# stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

# LogFile
log4j.appender.LogFile=org.apache.log4j.RollingFileAppender
log4j.appender.LogFile.File=${file.name}
log4j.appender.LogFile.layout=org.apache.log4j.PatternLayout
log4j.appender.LogFile.MaxFileSize=500KB
log4j.appender.LogFile.MaxBackupIndex=5
log4j.appender.LogFile.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

Basically for each of the components I'd like to log to a separate file, however the problem is that if I include log4j under the shared/lib directory, whichever webapp gets accessed first, effectively defines the log file that will be used by all of the webapps. i.e. I can't use a separate configuration.

The alternatives that I'm aware of: Put log4j into the WEB-INF/lib directory of each of the war files, that way I'll get a separate configuration per webapp.

Change "LogFile" reference above to be specific to each webapp, so that effectively a separate configuration is defined by each properties file. This seems to avoid the following error "log4j:ERROR A "org.apache.log4j.RollingFileAppender" object is not assignable to a "org.apache.log4j.Appender" variable."

i.e. use something like the following:

For WebApp1

log4j.rootLogger=DEBUG, LogFileWebapp1
# stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

# LogFile
log4j.appender.LogFileWebapp1=org.apache.log4j.RollingFileAppender
log4j.appender.LogFileWebapp1.File=${file.name}
log4j.appender.LogFileWebapp1.layout=org.apache.log4j.PatternLayout
log4j.appender.LogFileWebapp1.MaxFileSize=500KB
log4j.appender.LogFileWebapp1.MaxBackupIndex=5
log4j.appender.LogFileWebapp1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

For WebApp2

log4j.rootLogger=DEBUG, LogFileWebapp2
# stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

# LogFile
log4j.appender.LogFileWebapp2=org.apache.log4j.RollingFileAppender
log4j.appender.LogFileWebapp2.File=${file.name}
log4j.appender.LogFileWebapp2.layout=org.apache.log4j.PatternLayout
log4j.appender.LogFileWebapp2.MaxFileSize=500KB
log4j.appender.LogFileWebapp2.MaxBackupIndex=5
log4j.appender.LogFileWebapp2.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

I'd prefer to stick with the layout of the first properties file and keep it as similar as possible between the webapps, and would also perfer not to have to include a separate copy of log4j in each of the webapps. Ideally I was hoping to just use a symlink from the tomcat shared lib directory to the system copy of log4j.

Are there any other options?

A: 

I wouldn't do this. Let each webapp have its own log4j.jar and its own log4j.properties file. Otherwise you will never be able to upgrade log4j on just one webapp, and you will have a hard time modifying the logging for one application without affecting others.

Over and above maintenance pain and suffering, there's the possibility of causing a huge memory leak if log4j holds onto class references. Every time you redeploy Tomcat creates a new application classloader with new versions of all the classes, with no way to get rid of the old references because log4j doesn't know to let go of them, the only way to reclaim the memory is to restart the Tomcat instance.

Here's an interesting article on using container-level logging code. It does attempt to list ways to get around the memory leak problems, but the surest solution is to avoid the problem by keeping log4j in each app's WEB-INF/lib.

Nathan Hughes