Log4j2 还使用关闭挂钩来结束其服务。但当然我想记录我的应用程序的整个生命周期 - 包括关闭。对于 Log4j 这没有问题。现在看来是不可能了。日志记录关闭,而我的应用程序仍在处理它。有人对我有希望吗?
致以诚挚的问候 马丁
从 2.0-beta9 开始,现在可以在 xml 中配置
<configuration ... shutdownHook="disable">
考虑到它现在已被禁用,我想我需要在关闭挂钩末尾手动关闭日志系统。但是我找不到彻底外部接口的方法,只能在内部 api 中
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.LoggerContext;
...
public static void main(String[] args) {
final AnnotationConfigApplicationContext springContext = new AnnotationConfigApplicationContext(AppConfig.class)
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
//shutdown application
LOG.info("Shutting down spring context");
springContext.close();
//shutdown log4j2
if( LogManager.getContext() instanceof LoggerContext ) {
logger.info("Shutting down log4j2");
Configurator.shutdown((LoggerContext)LogManager.getContext());
} else
logger.warn("Unable to shutdown log4j2");
}
});
//more application initialization
}
更新:
LogManager.shutdown()
方法
我基本上只是回答了同样的问题,我很难在这里分享我的答案。我鼓励您阅读此处提供的完整答案。我将尝试在此处提供摘要,并根据当前情况调整我的答案。
在第一个版本中,Log4j 提供了一个 API 来手动调用关闭过程。由于我们不知道的原因,它已从第二个版本中删除。现在,正确的方法(根据不存在的文档)是提供您自己的
ShutdownCallbackRegistry
接口的实现,该接口负责关闭过程。
我为解决此问题所做的就是实现了我自己版本的
ShutdownCallbackRegistry
界面。它主要执行与默认实现相同的操作,但它不是将自身注册为 JVM 的关闭挂钩,而是等到手动调用为止。
您可以在 GitHub/DjDCH/Log4j-StaticShutdown 上找到完整的解决方案和说明,并在您自己的项目中使用它。基本上,最后,您只需在应用程序中执行以下操作:
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
try {
// Do your usual shutdown stuff here that need logging
} finally {
// Shutdown Log4j 2 manually
StaticShutdownCallbackRegistry.invoke();
}
}
}));
我不能毫无疑问地说这是完美的解决方案并且我的实现是完美的,但我尝试以正确的方式去做。无论您是否认为此解决方案合适,我都会很高兴听到您的反馈。
不久前我在我的 Java 应用程序中遇到了同样的问题:关闭挂钩已启动,但在 1-2 个日志条目之后,由于记录器的关闭过程,日志记录停止,如上所述。
由于我在应用程序中使用包装记录器类而无法访问其关闭挂钩,因此我选择将输出直接输出到 stdout 和 stderr,这使我能够验证关闭过程是否按设计工作。
System.println.out("shutting down servers");
您可能还需要验证 pod 配置 YAML 中是否启用了输出和错误流;就我而言,它开箱即用。