如果log4j2
未按照配置文件中的规定正确配置,我们就不会认为我们的应用正常运行。如何可靠地检测log4j2
初始化期间是否发生错误并从java打印到控制台上? (至少)有两个错误配置来源:
setConfiguration()
期间出现问题。这个问题是关于第二点。在初始化过程中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版。
答案 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);
}