首页 > 解决方案 > Java 日志记录 - MDC.put 延迟?

问题描述

我正在尝试设置一些日志记录。规范是每个 ip 有单独的日志。让我们暂时忘记大量文件。在我的 logback.xml 中,我有:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <property name="LOG_MAIN_FOLDER" value="./log/sifting" />

    <appender name="FILE-THREAD" 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>head0</defaultValue>
        </discriminator>

        <sift>

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

            <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                <Pattern>
                    %d{yyyy-MM-dd HH:mm:ss} %mdc [%thread] %level %logger{35} - %msg%n
                </Pattern>
            </encoder>

            <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
                <FileNamePattern>${LOG_MAIN_FOLDER}/${logFileName}.%i.log.zip</FileNamePattern>
                <MinIndex>1</MinIndex>
                <MaxIndex>10</MaxIndex>
            </rollingPolicy>

            <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
                <MaxFileSize>10MB</MaxFileSize>
            </triggeringPolicy>
          </appender>
        </sift>
    </appender>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>
                %-5level %logger{36} - %msg%n
            </Pattern>
        </layout>
    </appender>

    <logger name="poc.log.SiftingLog" level="debug" additivity="false">
        <appender-ref ref="FILE-THREAD" />
        <appender-ref ref="STDOUT" />
    </logger>

    <root level="error">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

And here is my code:

private void runTest() {
    for (int threadNo = 0; threadNo < 100; threadNo++) {
        new Thread(() -> {
            StringJoiner ip = new StringJoiner(".");
            for (int i = 0; i < 4; i++) ip.add(new Random().nextInt(256) + "");
            
            Logger logger = LoggerFactory.getLogger(SiftingLog.class);
            MDC.put("logFileName", getPathName(ip.toString()));
            logger.info(MDC.getCopyOfContextMap().get("logFileName"));
            
            
            logger.debug("hello " + ip.toString());
            try {Thread.sleep(200);} catch (InterruptedException e) {}
            logger.debug("working " + ip.toString());
            try {Thread.sleep(200);} catch (InterruptedException e) {}
            logger.debug("bye " + ip.toString());

            //remember remove this
            MDC.remove("logFileName");
        }).start();
    }
}

我希望将所有日志放在以 ip 命名的文件中。但是,正在创建 head0 日志文件,并且所有线程都将前两行('hello' 的 .info 和 .debug)放在默认日志文件中。休眠一段时间后,接下来的两条调试线都放置正确。

如何刷新 MDC.put 命令?我选择了 slf4j 和 SiftingLogger,因为它最容易找到任何教程/信息。如果任何其他库或工具更适合此任务,请告诉我。

标签: javaloggingslf4jmdc

解决方案


使 logger 成为常量,而不是在每个线程中初始化它,看看是否有帮助。

private static final Logger logger = LoggerFactory.getLogger(SiftingLog.class);


推荐阅读