【问题标题】:Log4J2 Programmatic Configuration from XML byte stream来自 XML 字节流的 Log4J2 编程配置
【发布时间】:2015-02-09 22:10:50
【问题描述】:

我对 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 的建议后,我在调用初始化方法之前添加了以下代码块:

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,我认为 Log4J2 代码中存在错误,当尝试使用 InputStream 进行初始化时,我的理论:

在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();
    }
}

【问题讨论】:

    标签: configuration initialization log4j2


    【解决方案1】:

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

    您可以尝试以下操作以生成更多 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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-27
      • 2015-11-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多