Sharing a single log4j jar file in Tomcat5 between multiple webapps with separate property files

一个人想着一个人 提交于 2020-01-02 07:27:53

问题


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?


回答1:


I wouldn't do this. Let each webapp have its own log4j.jar and its own log4j.properties file. Even if you get this working in all other respects, 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. It describes the problem you're seeing:

When you deploy log4j in the container's lib path for a container that is not "log4j-aware" and you don't set up a "Context Repository Selector" for log4j you lose a major feature - logging configuration becomes totally global across all components in the container. Only one logging configuration file is read (from the container's classpath) and every component in the container sees the same logging configuration. This is just not comparable to commons-logging at all. In most cases this is not acceptable behaviour; however commons-logging might provide a feature to behave in this manner if anybody actually thinks this is useful.

When you deploy log4j in the container's lib path and use the "Context Repository Selector" behaviour to get per-component logging configuration AND log4j is also in the component's path you get class cast exceptions (commons-logging currently suffers from the same issue). This is really a separate problem.

When you deploy log4j in the container's lib path and use the "Context Repository Selector" behaviour to get per-component logging configuration and log4j is not in the component's path then you will get memory leaks in exactly the same way as occurs for commons-logging, and for exactly the same reasons.

The easiest solution is to avoid the problem by keeping log4j in each app's WEB-INF/lib.



来源:https://stackoverflow.com/questions/3549226/sharing-a-single-log4j-jar-file-in-tomcat5-between-multiple-webapps-with-separat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!