logback1.11的一个bug:有线程持续不断写入log文件,log文件就不会按设定以日期切换。

此Bug的解决方案请见:https://www.cnblogs.com/xiandedanteng/p/12205422.html

logback是log4j的后继者,作者也是同一人,但其中的bug不可不知。

 

其中一个bug就是:当设定FileNamePattern为${LOG_HOME}/XXXX.%d{yyyy-MM-dd}.log后,如果有线程不断写log,即使过了零点,文件也不会更换到以新日期命名的新文件,而还是会在昨天命名的文件中不断写入。即使有新线程在零点之后启动写log,内容依旧会写入以昨天命名的文件里。简短来说就是有线程持续不断写入log文件,log文件就不会按设定以日期切换。

目前这个bug确认发生在logback1.11(logback-classic1.11.jar,logback-core1.11.jar,slf4j-api-1.7.22.jar)版本里,其它版本未知。下面结果在win10和linux中都可重现。

 

下面是我的logback配置文件,红字部分就是设定log按日期切换:

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!-- Where are log files -->
    <property name="LOG_HOME" value="d:/logs" />
    
    <!-- Output to Console -->
    <appender name="STDOUT"
        class="ch.qos.logback.core.ConsoleAppender">
        <encoder
            class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--%d:date,%thread:thread,%-5level:error/debug/info... %msg:message,%n:new line -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -%msg%n</pattern>
        </encoder>
    </appender>
    
    <!-- Output to File -->
    <appender name="FILE"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy
            class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--log file pathname -->
            <FileNamePattern>${LOG_HOME}/logbackCfg.log.%d{yyyy-MM-dd}.log
            </FileNamePattern>
            <!--days log files will be kept -->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder
            class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--%d:date,%thread:thread,%-5level:error/debug/info... %msg:message,%n:new line -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -%msg%n</pattern>
        </encoder>
        <!--size -->
        <triggeringPolicy
            class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <!-- log level TRACE, DEBUG, INFO, WARN, ERROR, ALL and OFF,default:DEBUG。-->
    <root level="ALL">
        <appender-ref ref="STDOUT" /> <!-- show log on console -->
        <appender-ref ref="FILE" /> <!-- show log in file -->
    </root>
</configuration>

我用来启动线程不断写log两个线程之一如下:

package logbackCfg;

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class Runner extends Thread {
    private String file;
    
    public Runner(String file) {
        this.file=file;
    }
    
    public void run() {
        while(true) {
            try {
                Thread.sleep(5000);
                Thread.currentThread().interrupt();
                
                File f=new File(file);
                FileWriter fw = new FileWriter(f, true);
                
                PrintWriter pw = new PrintWriter(fw);
                pw.println("追加内容");
                pw.println("落霞与孤鹜齐飞");
                pw.println("秋水共长天一色");
                pw.println("滕王阁序 唐.王勃");
                pw.flush();


                pw.close();
                fw.close();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

public class App {
    private final static Logger logger = LoggerFactory.getLogger(App.class);

    public static void main(String[] args) throws InterruptedException {
        //Runner r=new Runner("D:\\logs\\logbackCfg.log.2020-01-15.log");
        //r.start();
        
        while(true) {
            Thread.sleep(5000);
            logger.info("秦时明月汉时关");
            logger.error("万里长征人未还");
            logger.debug("但使龙城飞将在");
            logger.trace("不教胡马度阴山");
        }
    }
}

不断写入之二:

package logbackCfg;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;





public class App2 {
    private final static Logger logger = LoggerFactory.getLogger(App2.class);

    public static void main(String[] args) throws InterruptedException {
        
        while(true) {
            Thread.sleep(8000);
            logger.info("九里山前作战场");
            logger.error("牧童拾得旧刀枪");
            logger.debug("微风吹皱乌江水");
            logger.trace("恰似虞姬别霸王");
        }
    }
}

过了零点启动写log的线程如下:

package logbackCfg;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class NewDayThread {
    private final static Logger logger = LoggerFactory.getLogger(NewDayThread.class);

    public static void main(String[] args) throws InterruptedException {
        
        while(true) {
            Date currentTime = new Date();
            
            if(currentTime.compareTo(fixedDate())>0) {
                Thread.sleep(8000);
                logger.info("万里赴戎机,关山度若飞。");
                logger.error("朔气传金柝,寒光照铁衣。");
                logger.debug("将军百战死,壮士十年归。");
            }
        }
    }
    
    private static Date fixedDate() {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return formatter.parse("2020-01-17 00:00:00");
        } catch (ParseException e) {
            return new Date();
        }
    }
}

 

结果到了17日,log依旧在往16日的log中不断写入,下面是证据:

 

以上实现并不复杂,大家可以本地配置实验一下,看看情况如何,如果不想写代码,也可以从这里https://files.cnblogs.com/files/xiandedanteng/logbackCfg2020-01-17.zip下载。

--END-- 2020-01-1709:37

posted @ 2020-01-17 08:40  逆火狂飙  阅读(927)  评论(1编辑  收藏  举报
生当作人杰 死亦为鬼雄 至今思项羽 不肯过江东