如何使用Log4j2在关机钩子内记录日志?建议的解决方案
2022-09-01 18:49:08
Log4j2还使用关闭钩子来结束它的服务。但是,当然,我希望在应用程序的整个生命周期内进行记录 - 包括关闭。使用Log4j,这没有问题。现在看来这是不可能的。日志记录将关闭,而我的应用程序仍在处理它。有人对我抱有希望吗?
最好的问候马丁
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
}
更新:
我基本上只是回答了同样的问题,我很难在这里分享我的答案。我鼓励您阅读此处提供的完整答案。我将尝试在此处提供摘要,并根据当前上下文调整我的答案。
在第一个版本中,Log4j提供了一个API来手动调用关闭过程。由于我们不了解的原因,它已从第二个版本中删除。现在,正确的方法(根据不存在的文档)是提供您自己的 ShutdownCallbackRegistry
接口的实现,该接口负责关闭过程。
我解决这个问题的方法是,我实现了我自己的接口版本。它主要执行与默认实现相同的操作,但不是将自身注册为 JVM 的关闭挂钩,而是等到手动调用它。ShutdownCallbackRegistry
您可以在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();
}
}
}));
我不能毫无疑问地说这是完美的解决方案,我的实现是完美的,但我试图以正确的方式做到这一点。我很乐意听到您的反馈,无论您是否认为此解决方案合适。