如何在log4j2初始化期间捕获错误?

时间:2015-10-15 16:56:59

标签: java log4j2

如果log4j2未按照配置文件中的规定正确配置,我们就不会认为我们的应用正常运行。如何可靠地检测log4j2初始化期间是否发生错误并从java打印到控制台上? (至少)有两个错误配置来源:

  1. 配置文件完全丢失(或无效?)
  2. 配置文件有效,但在setConfiguration()期间出现问题。
  3. 这个问题是关于第二点。在初始化过程中log4j2内部看起来try{...} catch(e) { LOGGER.error("bla bla", e) }使得无法检测到这些问题。

    打印到控制台的错误是人类无法看到错误。我们宁愿让我们的应用程序崩溃!

    我很惊讶我找不到以编程方式询问log4j2的方法:"我是否得到了我要求的配置?"。有什么我忽略了吗?例如。某种方法来检测是否已经记录了任何

    背景

    以下是我们看到的控制台输出。是的,/path/to/file有权拒绝 - 我该如何检测到?

    2015-10-15 17:43:50,539 main ERROR FileManager (/path/to/file) java.io.FileNotFoundException: /path/to/file (Permission denied)
    2015-10-15 17:43:50,541 main ERROR Unable to invoke factory method in class class org.apache.logging.log4j.core.appender.FileAppender for element File. java.lang.reflect.InvocationTargetException
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:497)
            at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:136)
            at org.apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:794)
            at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:734)
            at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:726)
            at org.apache.logging.log4j.core.config.AbstractConfiguration.doConfigure(AbstractConfiguration.java:383)
            at org.apache.logging.log4j.core.config.AbstractConfiguration.initialize(AbstractConfiguration.java:161)
            at org.apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:173)
            at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:422)
            at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:494)
            at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:510)
            at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:199)
            at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:146)
            at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:41)
            at org.apache.logging.log4j.LogManager.getContext(LogManager.java:177)
            at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:447)
            at (our first call to org.apache.logging.log4j.LogManager.getLogger())
    

    查看LoggerContext.reconfigure()的代码,我看到了:

    private void reconfigure(final URI configURI) {
        <snip>
        final Configuration instance = ConfigurationFactory.getInstance().getConfiguration(name, configURI, cl);
        setConfiguration(instance);
        <snip>
    }
    

    setConfiguration()的来电期间,org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build中有此内容:

        try {
            <snip>
            final Object plugin = factory.invoke(null, params);
            <snip>
            return plugin;
        } catch (final Exception e) {
            LOGGER.error("Unable to invoke factory method in class {} for element {}.", this.clazz, this.node.getName(),
                e);
            return null;
        }
    

    问题不是来自getConfiguration()的{​​{1}},而是后来的ConfigurationFactory,而且似乎无法检测到存在问题......: - (

    关于第一点:配置文件完全丢失(或无效?)

    我们在java命令行上设置了setConfiguration(),并且已经有关于如何检测-Dlog4j.configurationFile=<file>是否缺失的several帖子。 One of which使用我们自己的<file>-Dlog4j.configurationFactory建议。但是,根据我的理由,在ConfigurationFactory ConfigurationFactory检测第二点(&#34; 2。&#34;以上)时,我们自己setConfiguration()的任何摆弄都无济于事。

    我们在debian stable / jessie上的openjdk 8上运行log4j2 2.4版。

1 个答案:

答案 0 :(得分:1)

事实证明,Log4j2内部使用特殊的StatusLogger,其中有getStatusData()方法,所以这里有什么:

    import org.apache.logging.log4j.status.StatusData;
    import org.apache.logging.log4j.status.StatusLogger;
    ...
    StatusLogger statusLogger = StatusLogger.getLogger();
    if (statusLogger.getStatusData().size() > 0) {
        System.out.printf(
                "Logged %d messages\n",
                statusLogger.getStatusData().size()
            );
        // Investigate List<StatusData> if you want
        for(StatusData data : statusLogger.getStatusData()) {
            System.out.printf(
                    "    Level %s message: %s\n",
                    data.getLevel(),
                    data.getMessage().getFormattedMessage()
                );
        }
        System.err.println("exiting due to unexpected console status logs");
        System.exit(1);
    }