java - 带有 Log4j2 的 Weblogic 12c 在停止/启动后停止记录

标签 java log4j weblogic log4j2 weblogic12c

当我们在 Weblogic 12c 中停止 war 然后重新开始时,我遇到了一个奇怪的行为。由于某种超出我理解的原因,Log4j2 停止写入日志。它会创建一个新的日志文件,但不会写入任何条目。

我已经调试并看到 Log4jServletContainerInitializer 和 Log4jServletContextListener 被调用,就像它们在安装 war 时一样。我没有注意到任何差异(不幸的是,这只是对我注意力持续时间的测试)。

那么,对于 Weblogic 12c 中的 Log4J2,安装和启动之间可能有什么不同,以及可能在哪里查找错误,您是否知道?

最佳答案

您的问题:

出于某种超出我理解的原因,Log4j2 停止写入日志。它会创建一个新的日志文件,但不会写入任何条目。


根本原因分析:

在某些问题上确实会发生这种情况。

  1. 如果您的 log4j 配置没有正确完成 log4j.properties 文件。
  2. 如果您的追加属性未变为真。
  3. 如果您使用两个记录器,例如 Log4JJUL,它们使用相同的 应用程序(标准输出)。
  4. 如果您的 log4j jar 文件没有正确设置到您的类路径。

解决方案:

答案 1: 在您的类路径中,有一个库设置可以拦截 Log4J 调用并将它们转换为 JUL 调用。那么它可能会导致这个问题。因此,请正确指定实际需要导入的内容。 java.util.logging.Loggerorg.apache.log4j.Logger

答案 2: 属性区分大小写。所以你的 文件名将与 appender 相同。并且不要忘记将 appender 设置为 true。

log4j.appender.mainAppender.File=yourLogFile.log
log4j.appender.mainAppender.Append=true

答案 3: 特别是对于 Hibernate,包括 slf4j 以确保所有记录器都与其合作。


答案 4: 有时候tomcat会出现这个问题。如果启用了 tomcat 安全性,并且策略文件中缺少多个权限,则会发生此类问题。授予权限后,它将正常工作。


Log4J 实际上做了什么?

Log4J 只会打印 info 和 up 的消息,并且会将它们打印到控制台和文件。您可以通过将 log4j.rootLogger 中的 INFO 更改为 ALL 来更改此行为。如果这不起作用,将 -Dlog4j.debug=true 添加到您的 JVM 参数 - 这将使 Log4J 发出关于自身的调试消息(到 System.out),这样您就可以看到发生了什么。 感谢@Isaac

资源链接:

  1. Log4J creates log file but does not write to it
  2. Issue with log4j log not writing to file

UPDATE for log4j2:


非常感谢 rgoers指出 log4j2 的问题。我正在更新。

来自 wilkinsona 的 P.O.V 的根本原因分析

当触发重启时,DevTools 运行然后清除所有已注册的关闭 Hook 。一个这样的 Hook 是 Log4J2 的 DefaultShutdownCallbackRegistry。 Log4jContextFactory 保留对 DefaultShutdownCallbackRegistry 的引用,而 LogManager 保留对 Log4jContextFactory 的静态引用。 Log4J2 的类由应用类加载器加载,这意味着在重新启动时共享一个 LogManager、Log4jContextFactory 和 DefaultShutdownCallbackRegistry。

DefaultShutdownCallbackRegistry 作为重启的一部分运行时,它会停止 LoggerContext 并将自己的状态设置为 STOPPED。随着重新启动的进行,将创建一个新的 LoggerContext,并尝试在注册表中为其注册一个关闭回调。这失败了,因为注册表的状态仍然是 STOPPED

解决方案:

Wilkinsona 提供了一种 hack 方法来解决这个问题。这在下面给出。尝试应对它。

在 Restarter 运行 JVM 的关闭 Hook 之前清除注册表中的回调更好。它可以防止异常发生,并且日志记录在重启后继续工作。

private void prepareLog4J2ForRestart() throws Exception {
    if (ClassUtils.isPresent("org.apache.logging.log4j.LogManager",
            getClass().getClassLoader())) {
        LoggerContextFactory factory = LogManager.getFactory();
        Field field = ReflectionUtils.findField(factory.getClass(),
                "shutdownCallbackRegistry");
        ReflectionUtils.makeAccessible(field);
        ShutdownCallbackRegistry shutdownCallbackRegistry = (ShutdownCallbackRegistry) ReflectionUtils
                .getField(field, factory);
        Field hooksField = ReflectionUtils
                .findField(shutdownCallbackRegistry.getClass(), "hooks");
        ReflectionUtils.makeAccessible(hooksField);
        @SuppressWarnings("unchecked")
        Collection<Cancellable> state = (Collection<Cancellable>) ReflectionUtils
                .getField(hooksField, shutdownCallbackRegistry);
        state.clear();
    }
}

资源链接:

  1. Log4j 2.4 breaks rc1 devtools
  2. Call context.close() rather than shutdown hook in DevTools restart

更新2:

What kind of listener to add to my JEE application, to get the expected behaviour?

要编写监听器,您可以按照教程

  1. ServletContextListener Example
  2. Writing a Listener Class
  3. Servlet Listener Example – ServletContextListener, HttpSessionListener and ServletRequestListener

关于java - 带有 Log4j2 的 Weblogic 12c 在停止/启动后停止记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36301694/

相关文章:

Java 正则表达式 : matches(pattern, 值)返回 true 但 group() 无法匹配

java - 使用 continue 在第二个 switch 语句上无法访问语句

java - spring-boot-starter-amqp 依赖导致 StackOverflowError

Java toString 将json(gson impl)放在日志中

log4j - 如何覆盖 Maven 插件的 log4j 配置?

javax.naming.NameNotFoundException :while trying to lookup

java - 使用循环分配按钮

java - 确定正确状态字符串的条件逻辑

java - 网络逻辑: How to Download/Upload files from front-end (File Store ?)

linux - weblogic server 11g 内存不足问题