带有 Log4j2 的 Weblogic 12c 在 stop/start 后停止记录
Weblogic 12c with Log4j2 stops logging after stop/start
当我们在 Weblogic 12c 中停止 war 然后再次启动它时,我遇到了一个奇怪的行为。由于某种超出我理解的原因,Log4j2 停止写入日志。它会创建一个新的日志文件,但不会写入任何条目。
我已经调试并看到 Log4jServletContainerInitializer 和 Log4jServletContextListener 被调用,就像它们在安装 war 时一样。我没有注意到任何差异(不幸的是,这只是对我注意力持续时间的测试)。
那么,对于 Weblogic 12c 中的 Log4J2,安装和启动之间可能有什么不同,以及可能在哪里查找错误,您是否知道?
您的问题:
出于某种超出我理解的原因,Log4j2 停止写入日志。它会创建一个新的日志文件,但不会写入任何条目。
根本原因分析:
有些问题确实会发生。
- 如果您的 log4j 配置不正确
log4j.properties
文件。
- 如果您的追加属性未变为真。
- 如果您使用两个记录器,如
Log4J
和 JUL
,它们使用相同的
应用程序(标准输出)。
- 如果您的 log4j jar 文件没有正确设置到您的类路径。
解决方案:
答案 1:
在您的类路径中,有一个库设置可以拦截 Log4J 调用并将它们转换为 JUL 调用。那么它可能会导致这个问题。因此,请正确指定实际需要导入的内容。 java.util.logging.Logger
或 org.apache.log4j.Logger
答案 2:
属性为 case sensitive
。所以你的file name would be same with appender
。并且不要忘记将 appender 设置为 true。
log4j.appender.mainAppender.File=yourLogFile.log
log4j.appender.mainAppender.Append=true
答案 3:
特别是对于 Hibernate,包括 slf4j 以确保所有记录器与其合作。
答案4:
tomcat 有时会出现此问题。如果 tomcat 安全启用,并且策略文件中缺少多个权限,则会出现此类问题。给权限后就可以正常使用了
Log4J 实际上做了什么?
Log4J 只会打印 info 及以上的消息,并且会将它们打印到控制台和文件中。您可以通过在 log4j.rootLogger
中将 INFO
更改为 ALL
来更改此行为。如果这不起作用,请将 -Dlog4j.debug=true
添加到您的 JVM 参数 - 这将使 Log4J 发出关于自身的调试消息(到 System.out),这样您就可以看到发生了什么。
感谢@Isaac
资源Link:
- Log4J creates log file but does not write to it
- Issue with log4j log not writing to file
UPDATE for log4j2:
非常感谢 rgoers 指出 log4j2 的问题。我正在更新。
来自 wilkinsona 的 P.O.V 的根本原因分析
当触发 restart
时,DevTools 运行s 然后清除所有已注册的关闭挂钩。一种这样的钩子是 Log4J2 的 DefaultShutdownCallbackRegistry
。 Log4jContextFactory 维护对 DefaultShutdownCallbackRegistry
的引用,而 LogManager 持有对 Log4jContextFactory 的静态引用。 Log4J2's classes are loaded by the app classloader which means that there's a single LogManager, Log4jContextFactory, and DefaultShutdownCallbackRegistry shared across restarts.
当 DefaultShutdownCallbackRegistry
是 运行 作为重新启动的一部分时,它会停止 LoggerContext
并将自己的状态设置为 STOPPED
。随着重新启动的进行,将创建一个新的 LoggerContext
并尝试在注册表中为其注册一个关闭回调。这失败了,因为注册表的状态仍然是 STOPPED
.
解决方案:
Wilkinsona 提供了一种 hack 方法来解决这个问题。这在下面给出。努力应对。
在 Restarter 运行JVM 的关闭挂钩之前清除注册表中的回调更好。它可以防止异常发生,并且 日志记录在重新启动后继续工作。
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();
}
}
资源Link:
更新 2:
What kind of listener to add to my JEE application, to get the
expected behaviour?
监听器的编写,可以按照教程进行
当我们在 Weblogic 12c 中停止 war 然后再次启动它时,我遇到了一个奇怪的行为。由于某种超出我理解的原因,Log4j2 停止写入日志。它会创建一个新的日志文件,但不会写入任何条目。
我已经调试并看到 Log4jServletContainerInitializer 和 Log4jServletContextListener 被调用,就像它们在安装 war 时一样。我没有注意到任何差异(不幸的是,这只是对我注意力持续时间的测试)。
那么,对于 Weblogic 12c 中的 Log4J2,安装和启动之间可能有什么不同,以及可能在哪里查找错误,您是否知道?
您的问题:
出于某种超出我理解的原因,Log4j2 停止写入日志。它会创建一个新的日志文件,但不会写入任何条目。
根本原因分析:
有些问题确实会发生。
- 如果您的 log4j 配置不正确
log4j.properties
文件。 - 如果您的追加属性未变为真。
- 如果您使用两个记录器,如
Log4J
和JUL
,它们使用相同的 应用程序(标准输出)。 - 如果您的 log4j jar 文件没有正确设置到您的类路径。
解决方案:
答案 1:
在您的类路径中,有一个库设置可以拦截 Log4J 调用并将它们转换为 JUL 调用。那么它可能会导致这个问题。因此,请正确指定实际需要导入的内容。 java.util.logging.Logger
或 org.apache.log4j.Logger
答案 2:
属性为 case sensitive
。所以你的file name would be same with appender
。并且不要忘记将 appender 设置为 true。
log4j.appender.mainAppender.File=yourLogFile.log
log4j.appender.mainAppender.Append=true
答案 3: 特别是对于 Hibernate,包括 slf4j 以确保所有记录器与其合作。
答案4: tomcat 有时会出现此问题。如果 tomcat 安全启用,并且策略文件中缺少多个权限,则会出现此类问题。给权限后就可以正常使用了
Log4J 实际上做了什么?
Log4J 只会打印 info 及以上的消息,并且会将它们打印到控制台和文件中。您可以通过在 log4j.rootLogger
中将 INFO
更改为 ALL
来更改此行为。如果这不起作用,请将 -Dlog4j.debug=true
添加到您的 JVM 参数 - 这将使 Log4J 发出关于自身的调试消息(到 System.out),这样您就可以看到发生了什么。
感谢@Isaac
资源Link:
- Log4J creates log file but does not write to it
- Issue with log4j log not writing to file
UPDATE for log4j2:
非常感谢 rgoers 指出 log4j2 的问题。我正在更新。
来自 wilkinsona 的 P.O.V 的根本原因分析
当触发 restart
时,DevTools 运行s 然后清除所有已注册的关闭挂钩。一种这样的钩子是 Log4J2 的 DefaultShutdownCallbackRegistry
。 Log4jContextFactory 维护对 DefaultShutdownCallbackRegistry
的引用,而 LogManager 持有对 Log4jContextFactory 的静态引用。 Log4J2's classes are loaded by the app classloader which means that there's a single LogManager, Log4jContextFactory, and DefaultShutdownCallbackRegistry shared across restarts.
当 DefaultShutdownCallbackRegistry
是 运行 作为重新启动的一部分时,它会停止 LoggerContext
并将自己的状态设置为 STOPPED
。随着重新启动的进行,将创建一个新的 LoggerContext
并尝试在注册表中为其注册一个关闭回调。这失败了,因为注册表的状态仍然是 STOPPED
.
解决方案:
Wilkinsona 提供了一种 hack 方法来解决这个问题。这在下面给出。努力应对。
在 Restarter 运行JVM 的关闭挂钩之前清除注册表中的回调更好。它可以防止异常发生,并且 日志记录在重新启动后继续工作。
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();
}
}
资源Link:
更新 2:
What kind of listener to add to my JEE application, to get the expected behaviour?
监听器的编写,可以按照教程进行