如何使用 Log4j2 在 shutdown hooks 中登录?

问题描述 投票:0回答:3

Log4j2 还使用关闭挂钩来结束其服务。但当然我想记录我的应用程序的整个生命周期 - 包括关闭。对于 Log4j 这没有问题。现在看来是不可能了。日志记录关闭,而我的应用程序仍在处理它。有人对我有希望吗?

致以诚挚的问候 马丁

java logging log4j2 application-shutdown
3个回答
37
投票

从 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 2.6 版本开始就有

LogManager.shutdown()
方法


9
投票

我基本上只是回答了同样的问题,我很难在这里分享我的答案。我鼓励您阅读此处提供的完整答案。我将尝试在此处提供摘要,并根据当前情况调整我的答案。

在第一个版本中,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();
        }
    }
}));

我不能毫无疑问地说这是完美的解决方案并且我的实现是完美的,但我尝试以正确的方式去做。无论您是否认为此解决方案合适,我都会很高兴听到您的反馈。


0
投票

不久前我在我的 Java 应用程序中遇到了同样的问题:关闭挂钩已启动,但在 1-2 个日志条目之后,由于记录器的关闭过程,日志记录停止,如上所述。

由于我在应用程序中使用包装记录器类而无法访问其关闭挂钩,因此我选择将输出直接输出到 stdout 和 stderr,这使我能够验证关闭过程是否按设计工作。

System.println.out("shutting down servers");

您可能还需要验证 pod 配置 YAML 中是否启用了输出和错误流;就我而言,它开箱即用。

© www.soinside.com 2019 - 2024. All rights reserved.