每个请求在一个文件中记录不同的日志框架

logging of different log frameworks in one file per request

我有一个 java jaxrs 网络服务器,其中有很多 classes。每个 class 使用不同的日志框架。大部分使用slf4j,部分使用org.apache.commons.logging。此外,我在使用 log4j 进行日志记录的程序中使用 hadoop 1.2.0。

我希望每个请求有不同的日志文件(每个请求 运行 的线程)和服务器的不同日志文件。 我为此目标使用了 MDC 和 siftingappender,但只有 slf4j 日志文件写入线程日志。 hadoop 日志写在不同的日志文件中,apache.commons.logging 日志写在服务器日志文件中。 我应该怎么做才能将每​​个请求的日志保存在一个文件中。

请考虑我不想将所有日志文件更改为 log4j,因为 classes 很多。我也不能更改 hadoop 日志框架,因为它是一个 jar 文件。

有人可以帮助我吗? (如果我的英语不好,我深表歉意。)

我找到了集成所有日志框架的解决方案,使用slf4j。我将 log4j-over-slf4j.jar 和 jcl-over-slf4j.jar 添加到我的库中。所以 log4j 和 org.apache.commons.logging 根据 this.

使用 slf4j 配置进行日志记录

但这还不够,我还遇到了问题! Hadoop 作业日志未写入其请求线程日志文件。事实上,我的新问题是:"Hadoop jobs don't inherent MDC log values!"。我通过为每个新请求创建新的 logback.xml 来解决它,并使用 JoranConfigurator.doConfigure().

将其设置为新的配置文件

这是我的 logback.xml

<appender name="FILE" class="ch.qos.logback.classic.sift.SiftingAppender">

    <!-- This is MDC value -->
    <!-- We will assign a value to 'logFileName' via Java code -->
    <discriminator>
        <key>logFileName</key>
        <defaultValue>server</defaultValue>
    </discriminator>

    <sift>

      <!-- A standard RollingFileAppender, the log file is based on 'logFileName' at runtime  -->
      <appender name="FILE-${logFileName}"
        class="ch.qos.logback.core.FileAppender">
        <file>${USER_HOME}/${logFileName}.log</file>

        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>
                %d{ISO8601} %level %X{logName} : %logger{30} - %msg%n
            </Pattern>
        </encoder>

      </appender>

    </sift>
</appender>

<root level="info">
    <appender-ref ref="FILE" />
</root>

我的程序复制此文件并将 logFileName 默认值更改为我想要的字符串。然后使用此代码将新文件设置为配置。

    // assume SLF4J is bound to logback in the current environment
    LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();

    try {
      JoranConfigurator configurator = new JoranConfigurator();
      configurator.setContext(context);
      // Call context.reset() to clear any previous configuration, e.g. default 
      // configuration. For multi-step configuration, omit calling context.reset().
      context.reset(); 
      configurator.doConfigure(newPath+"/logback.xml");
    } catch (JoranException je) {
      // StatusPrinter will handle this
    }
    StatusPrinter.printInCaseOfErrorsOrWarnings(context);