14

我正在构建一个部署到在 Linux 上运行的 WebSphere Portal Server 的 Portlet 应用程序。每个 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

部署后,一切都像魅力一样工作,日志文件开始填充。几个小时后,同时,记录停止并且info.log根本debug.log没有更新。我们需要在服务器中重新部署 Portlet WAR 以重新开始记录。

有任何想法吗?

更新:

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

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

第二次更新:

在从赏金到结束的几个小时内,这就是 Log4j 在每个 Portlet 应用程序中的配置方式。这是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>

miAppLog4j.properties文件位于 WAR 和 Portal 外部的文件夹中。我们通过WebSphere Portal 中的共享库使其在 Portlet Classpath 中可用。

4

5 回答 5

25

您已经提供了一些基本信息,所以我只能概述一些候选原因和可能性:

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

  • 由日志滚动触发?

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

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

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

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

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

    文件commons-logging.properties

    # 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 之一或使用 PropertyConfigurator.configureAndWatch 或 DOMConfigurator.configureAndWatch 时方法被调用。

3. ClassLoaders中Log4J类的变化,使用不同的配置?

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

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

    很可能是一个问题——Google 上的数千名用户一直在为 Websphere 类加载器而苦苦挣扎。

建议的行动:

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

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

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

这是很多文字............ B^)

于 2013-02-26T05:50:24.867 回答
4

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

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

于 2013-03-01T09:50:11.087 回答
3

我认为问题在于您有多个 WAR 写入同一个日志文件。根据我们的经验,log4j 不能可靠地做到这一点,尤其是使用滚动附加程序。当一个人去滚动它时,其他人会感到困惑并且无法进一步记录。或者继续登录到旧文件。

我怀疑您将不得不将每个 WAR 日志记录到不同的文件中。

于 2013-01-10T14:35:58.790 回答
0

我会尝试将日志文件位置移动到临时文件系统以外的地方。

于 2013-01-10T13:14:44.083 回答
-2

我不确定为什么 log4j 在您的应用程序中停止。但是您可以(应该)升级到 log4j 2.0。切换应该不会很费力。您需要将 log4j.properties 文件重写为 XML 文件,因为新版本不再支持属性文件。

在 Java Magazin 中的一篇文章指出,log4j 2.0 在多线程环境中表现得更加健壮,因此它有可能解决您的问题。如果没有,您仍然可以享受新版本的好处。

它带来了一些不错的功能和增强功能(从log4j站点复制):

API 分离

Log4j 的 API 与实现分开,使应用程序开发人员清楚地知道他们可以使用哪些类和方法,同时确保向前兼容性。这允许 Log4j 团队以安全且兼容的方式改进实现。

提高性能

Log4j 2 在关键领域的执行速度比 Log4j 1.x 快,并且在大多数情况下与 Logback 类似。有关详细信息,请参阅性能。支持多个 API 虽然 Log4j 2 API 将提供最佳性能,但 Log4j 2 提供对 SLF4J 和 Commons Logging API 的支持。

自动重新加载配置

与 Logback 一样,Log4j 2 可以在修改时自动重新加载其配置。与 Logback 不同,它会在重新配置时这样做而不会丢失日志事件。

高级过滤

与 Logback 一样,Log4j 2 支持基于上下文数据、标记、正则表达式和 Log 事件中的其他组件进行过滤。可以指定过滤以在传递给 Logger 之前或在它们通过 Appender 时应用于所有事件。此外,过滤器也可以与 Loggers 关联。与 Logback 不同,您可以在任何这些情况下使用通用的 Filter 类。

插件架构

Log4j 使用插件模式来配置组件。因此,您无需编写代码来创建和配置 Appender、Layout、Pattern Converter 等。Log4j 自动识别插件并在配置引用它们时使用它们。

物业支持

您可以在配置中引用属性,Log4j 将直接替换它们,或者 Log4j 将它们传递给将动态解析它们的底层组件。属性来自配置文件中定义的值、系统属性、环境变量、ThreadContext Map 和事件中存在的数据。用户可以通过添加自己的查找插件来进一步自定义属性提供者。

于 2013-03-01T16:35:54.670 回答