Log4j 突然停止日志记录

2022-09-03 18:16:14

我正在构建一个 Portlet 应用程序,该应用程序部署到在 Linux 上运行的 WebSphere Portal Server 上。每个 Portlet WAR 都使用 Log4j 进行日志记录,其配置如下所示,每个 WAR 都有两个日志文件:

log4j.logger.im.the.package=DEBUG, InfoAppender, DebugAppender

log4j.appender.InfoAppender=org.apache.log4j.RollingFileAppender
log4j.appender.InfoAppender.Threshold=INFO
log4j.appender.InfoAppender.File=/tmp/infoWARName.log
log4j.appender.InfoAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.InfoAppender.layout.ConversionPattern=%d %p [%c] - %m%n

log4j.appender.DebugAppender=org.apache.log4j.RollingFileAppender
log4j.appender.DebugAppender.Threshold=DEBUG
log4j.appender.DebugAppender.File=/tmp/debugWARName.log
log4j.appender.DebugAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.DebugAppender.layout.ConversionPattern=%d %p [%c] - %m%n

部署后,一切工作方式都像超级按钮一样,日志文件开始填充。几个小时后,同时,日志记录将停止,并且根本不会更新。我们需要在服务器中重新部署 Portlet WAR,以便再次启动日志记录。info.logdebug.log

有什么想法吗?

更新:

我开始怀疑这与我的日志记录JARS有关。目前,这是我的文件夹中的JAR:WEB-INF/lib

com.springsource.org.apache.commons.logging-1.1.1.jar
com.springsource.org.apache.log4j-1.2.15.jar
com.springsource.slf4j.api-1.5.6.jar
slf4j-log4j12-1.5.6.jar

第二次更新:

从赏金到结束的几个小时内,这就是每个 Portlet 应用程序中 Log4j 的配置方式。这里是:web.xml

<context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>classpath:miAppLog4j.properties</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

文件位于 WAR 和门户外部的文件夹中。我们通过 WebSphere Portal 中的共享库在 Portlet Classpath 中提供了它。miAppLog4j.properties


答案 1

你已经提供了一些基本信息,所以我只能勾勒出一些候选的原因和可能性:

1. 文件锁定/句柄/IO 流问题

  • 由日志滚动触发?

    在你的情况下是负面的。对于任何给定的 WAR,两个单独的日志文件(信息和调试)将同时停止。每个文件以默认的最大大小 (10MB) 滚动。两个日志不太可能总是同时滚动。该错误不得由日志滚动触发。通过配置进行额外确认log4j.appender.InfoAppender.MaxFileSize=200MB

  • 由用户操纵 Linux 文件触发?

    在你的情况下是负面的。用户/系统管理员操作文件可能会创建锁定或过时的文件句柄。Linux应该永远不会有用户尾随文件的问题(但Windows确实如此)。Linux 在用户压缩或编辑文件时可能会遇到问题。但是您的问题似乎非常可重复,除非您有自动脚本操作日志文件,否则这不太可能发生。

  • 由Websphere或Spring中的“竞争性”配置设置触发,服务器/框架重复使用相同的日志文件?

    在你的情况下似乎不太可能。似乎您还没有设置Websphere共享资源日志记录配置。共享资源日志记录自动包含在 websphere 服务器父 ClassLoader 中,并且可以通过配置以下内容配置为“包装”到 Log4J:

    文件共享资源-日志记录.属性

    # Set application classloader mode as PARENT_LAST when deploying in WAS as .ear
    priority=1
    org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl
    
  • 由硬件问题/磁盘故障触发?

    ???似乎很奇怪,这样的问题会非常可重复。

2. Java线程有问题?

  • 线程死机或死锁
  • “其他”代码中的大量线程处理/争用,因此不会运行带有日志记录的代码

    根据你的描述,我假设应用程序仍在运行,并且在正常的性能和功能下工作正常,但日志没有写入。你能确认吗?如果是这样,那么这不是webapp线程的线程问题。

    我还可以确认它不是Log4J逻辑中的线程问题,因为它创建/使用自己的线程的唯一时间是当使用AsynchAppender/ExternallyRolledFileAppender/SocketAppender/TelnetAppender之一时,或者当属性Configurator.configureAndWatch或DOMConfigurator.configureAndWatch方法被调用时。

    否定

3. 在类加载器中更改 Log4J 类,使用不同的配置?

  • 父类加载器与 Webapp 类加载器冲突

    例如,您的Web应用程序最初从WEBINF目录中使用自己配置的类开始,一切都很好,但后来不同的应用程序导致(或门户服务器管理工具之一)导致冲突类加载到父类加载器中,并且您的应用程序“拾取”这个新的非法版本的类并失败。

    很可能是一个问题 - Google上有成千上万的用户在Websphere类加载器上挣扎。

建议的操作:

  • 确保您的所有网络应用都使用PARENT_LAST类加载 - 转到管理控制台,确保它们在所有 WebApp 配置中都设置了PARENT_LAST

  • 确保您收到写入控制台的Log4J内部错误消息,例如,在应用程序运行时以管理员身份强制删除错误日志,从而创建过时的句柄,从而故意进行测试。如果控制台中未出现“Log4J:”错误消息,则这是一个严重的问题。
    下次出现问题时,请捕获任何此类控制台消息并报告它们。此外,您可以在JVM / websphere启动时设置“-D log4j.debug”,以准确了解Log4J在问题发生之前/期间正在做什么 - 消息将转到控制台。

  • 你真的需要为所有包和类设置日志记录级别到DEBUG吗?最好设置为 INFO 或 WARN,并且仅在调试特定问题时才有选择地设置为 on?

那是很多文字。B^)


答案 2

5年多来,Log4j几乎没有修复任何错误:它实际上是一个死项目。如果可以接受,请考虑将其替换为Logback,它直接实现SLF4j。

Logback和SLF4J是由编写Log4J(Ceki)的同一个人编写的,拥有更自由的许可证,并拥有良好的社区。它是Log4J 1的继承者(除了它的名字)。


推荐