在Tomcat5中,多个具有独立属性文件的webapp之间共享一个log4j jar文件[英] Sharing a single log4j jar file in Tomcat5 between multiple webapps with separate property files

本文是小编为大家收集整理的关于在Tomcat5中,多个具有独立属性文件的webapp之间共享一个log4j jar文件的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

是否可以在tomcat 5.5设置中使用单个log4j jar文件,可以在其中使用多个WebApps使用并为每个WebApp使用单独的日志记录?

我写了大约8个不同的WebApps,其中log4j属性文件之间唯一真正的区别是日志文件名.但是,如果我尝试将log4j从WebApp Web-Inf/lib目录转移到tomcat5共享/lib目录中,我会遇到问题.

所有属性文件基本上看起来与下面的文件相同,其中我刚刚在代码中使用system.setproperty(" file.name")设置file.name.不是真的,但是我在玩弄所有组件的单个属性文件的想法.

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

基本上,对于我想登录到单独文件的每个组件,但是问题是,如果我在共享/lib目录下包含log4j,则首先访问WebApp的哪个,有效地定义了将被定义的日志文件所有WebApps都使用.即我不能使用单独的配置.

我知道的替代方案: 将log4j放入每个战争文件的Web-Inf/lib目录中,这样我将获得每个WebApp的单独配置.

更改上面的" logfile"引用是针对每个WebApp的特定的,因此每个属性文件有效地定义了单独的配置.这似乎避免了以下错误" log4j:错误a" org.apache.log4j.rollingfileappender"对象"不可分配给" org.apache.apache.log4j.appender"变量. "

即.使用以下内容:

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

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

我宁愿坚持第一个属性文件的布局,并在WebApps之间保持尽可能相似,并且也将不必在每个WebApps中包含Log4j的单独副本.理想情况下,我希望只使用tomcat共享lib目录的符号链接到log4j的系统副本.

还有其他选项吗?

推荐答案

我不会这样做.让每个WebApp都有自己的log4j.jar及其自己的log4j.properties文件.即使您在所有其他方面都可以使用此功能,您将永远无法在一个WebApp上升级Log4J,并且您将很难修改一个应用程序的日志记录而不会影响其他应用程序.

在维持疼痛和痛苦之外,如果Log4J持有类参考,则可能会导致巨大的内存泄漏.每当您重新部署Tomcat时,都会使用所有类的新版本创建一个新的应用程序classloader,而无法摆脱旧的参考文献tomcat实例.

这是一篇有趣的文章它描述了您看到的问题:

当您在容器的LIB路径中部署log4j时 不是" log4j-ware",也不会设置"上下文存储库 选择器"对于log4j,您会丢失主要功能 - 记录配置 在容器中的所有组件中都变得完全全球.仅有的 读取一个记录配置文件(从容器的 classPath)和容器中的每个组件都可以看到相同的日志记录 配置.这完全不可与Commons-Goging相提并论. 在大多数情况下,这是不可接受的行为.然而 如果Commons-Goging可能会提供以这种方式行事的功能 任何人实际上都认为这很有用.

当您在容器的LIB路径中部署log4j并使用"上下文 存储库选择器"行为以获取每组日志记录 配置和log4j也在组件路径中 铸造例外(Commons-Logging目前遭受相同的苦难 问题).这确实是一个单独的问题.

当您在容器的LIB路径中部署log4j并使用"上下文 存储库选择器"行为以获取每组日志记录 配置和log4j不在组件的路径中 以完全相同的方式获取内存泄漏 commonging,出于完全相同的原因.

最简单的解决方案是通过将log4j保留在每个应用程序的Web-Inf/lib中来避免问题.

本文地址:https://www.itbaoku.cn/post/1574940.html

问题描述

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?

推荐答案

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.