来自XML字节流的Log4J2编程配置

时间:2015-02-09 22:10:51

标签: configuration initialization log4j2

我在Log4J2系列的最后,希望有人可以提供帮助。我在启动后很快就有了以下代码来初始化Log4J2:

try (InputStream configStream = new ByteArrayInputStream(writer.toString().getBytes("UTF-8"))) {            
    ConfigurationSource configurationSource = new ConfigurationSource(configStream);
    Configurator.initialize(null, configurationSource);
}

其中writer是StringWriter,而toString()产生以下配置(我通过其他方式验证了它是正确的):

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <Console name="C" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss,SSS z} %-5p %m%n"/>
        </Console>
        <RollingFile name="R" fileName="C:\temp\logfile.log" filePattern="C:\temp\logfile.log.%d{yyyy-MM-dd}">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss,SSS z} %-5p [%t] %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
            </Policies>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Logger name="somename" level="debug">
            <appender-ref ref="R"/>
        </Logger>
        <Root level="debug" additivity="false">
            <appender-ref ref="C" level="info"/>
        </Root>
    </Loggers>
</Configuration>

正如您可能已经猜到的那样,这不起作用,除了预期之外我没有收到任何错误消息:

ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.

我之所以这么说是因为我手动配置Log4J2并且还没有抑制此消息。

不幸的是,由于遗留原因,我无法从文件中读取配置。

更新1:

在接受Remko的建议后,我在调用initialize方法之前添加了以下块:

System.setProperty("log4j2.disable.jmx", "true");
StatusLogger status = StatusLogger.getLogger();
status.clear(); // remove old listeners that may prevent status output
status.setLevel(Level.TRACE);
status.reset(); // I could not see any trace info until I called this
status.trace("Status -- TRACE"); // I added this to prove that trace level logging was working

这给了我以下输出:

ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
TRACE StatusLogger Status -- TRACE
DEBUG StatusLogger Stopping LoggerContext[name=sun.misc.Launcher$AppClassLoader@647e05, org.apache.logging.log4j.core.LoggerContext@a3defe]
DEBUG StatusLogger Stopping LoggerContext[name=sun.misc.Launcher$AppClassLoader@647e05, org.apache.logging.log4j.core.LoggerContext@a3defe]...
DEBUG StatusLogger Unregistering MBean org.apache.logging.log4j2:type=sun.misc.Launcher$AppClassLoader@647e05
DEBUG StatusLogger Unregistering MBean org.apache.logging.log4j2:type=sun.misc.Launcher$AppClassLoader@647e05,component=StatusLogger
DEBUG StatusLogger Unregistering MBean org.apache.logging.log4j2:type=sun.misc.Launcher$AppClassLoader@647e05,component=ContextSelector
DEBUG StatusLogger Unregistering MBean org.apache.logging.log4j2:type=sun.misc.Launcher$AppClassLoader@647e05,component=Appenders,name=Console
TRACE StatusLogger Stopping org.apache.logging.log4j.core.config.DefaultConfiguration@1a1440e...
TRACE StatusLogger AbstractConfiguration stopped 0 AsyncLoggerConfigs.
TRACE StatusLogger AbstractConfiguration stopped 0 AsyncAppenders.
DEBUG StatusLogger Shutting down OutputStreamManager SYSTEM_OUT
TRACE StatusLogger AbstractConfiguration stopped 1 Appenders.
TRACE StatusLogger AbstractConfiguration stopped 0 Loggers.
DEBUG StatusLogger Stopped org.apache.logging.log4j.core.config.DefaultConfiguration@9a6398 OK
DEBUG StatusLogger Stopped LoggerContext[name=sun.misc.Launcher$AppClassLoader@647e05, org.apache.logging.log4j.core.LoggerContext@9a6398]...

更新2:

我决定找出一种方法来处理文件而不是ByteArrayInputStream并使其正常工作。 FWIW,我认为在尝试使用InputStream进行初始化时,Log4J2代码中存在一个错误,我的理论是:

在Log4jContextFactory中使用以下方法:

public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext,
                                final boolean currentContext, final ConfigurationSource source)

具有以下if语句,该语句始终计算为false,这意味着始终返回默认配置...

if (ctx.getState() == LifeCycle.State.INITIALIZED) {
    if (source != null) {
        ContextAnchor.THREAD_CONTEXT.set(ctx);
        final Configuration config = ConfigurationFactory.getInstance().getConfiguration(source);
        LOGGER.debug("Starting LoggerContext[name={}] from configuration {}", ctx.getName(), source);
        ctx.start(config);
        ContextAnchor.THREAD_CONTEXT.remove();
    } else {
        ctx.start();
    }
}

1 个答案:

答案 0 :(得分:0)

乍一看,我不明白为什么你的配置不起作用。 (你可以尝试在路径中使用正斜杠来绝对确定,但很可能斜杠不是问题。)

您是否可以尝试以下方法生成更多log4j2调试输出以查看配置出错的位置?请将结果发布在您的问题中。

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.status.StatusLogger;

// In an XML configuration you can just use <Configuration status="TRACE"...
// Here we use less elegant code to switch on status logging 
// since we're not sure where things break down.
System.setProperty("log4j2.disable.jmx", "true");
StatusLogger status = StatusLogger.getLogger();
status.clear(); // remove old listeners that may prevent status output
status.setLevel(Level.TRACE);

// now configure log4j2...
// This should generate trace-level debug output to the console.
try (InputStream configStream = new ByteArrayInputStream(writer.toString().getBytes())) {            
    ConfigurationSource configurationSource = new ConfigurationSource(configStream);
    Configurator.initialize(null, configurationSource);
}