修改log4j的生成日志策略(一天一个目录,每次重启日志文件切换新的)

功能如标题,代码如下

MyRollingFileAppender
package com.source.util;

import org.apache.log4j.Layout;
import org.apache.log4j.Priority;
import org.apache.log4j.RollingFileAppender;
import org.apache.log4j.helpers.CountingQuietWriter;
import org.apache.log4j.spi.LoggingEvent;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.Date;

/**
 * 修改log的生成策略(一天一个目录,每次重启日志文件切换新的)
 *
 * @author source
 */
@SuppressWarnings("Duplicates")
public class MyRollingFileAppender extends RollingFileAppender {
    private LocalDate localDate = null;
    private String parternFileName = null;

    /**
     * 默认的无参构造
     */
    public MyRollingFileAppender() {
        super();
    }

    /**
     * 三参构造
     */
    public MyRollingFileAppender(Layout layout, String filename, boolean append) throws IOException {
        super(layout, filename, append);
        parternFileName = filename;
    }

    /**
     * 二参构造(append->true)
     */
    public MyRollingFileAppender(Layout layout, String filename) throws IOException {
        super(layout, filename);
    }

    /**
     * 修改fileName方法在截断生成新文件前调用
     */
    @Override
    public void setFile(String file) {
        if (parternFileName == null) {
            parternFileName = file;
        }
        super.fileName = DatePatternParser.parse(new StringBuilder(parternFileName));
    }

    /**
     * 当前日志输出行只输出到对应的日志等级文件(不做向下兼容)
     */
    @Override
    public boolean isAsSevereAsThreshold(Priority priority) {
        return this.getThreshold().equals(priority);
    }


    /**
     * 修改日志策略主要逻辑
     */
    @Override
    protected void subAppend(LoggingEvent event) {
        boolean rollOver = false;
        //重启且有日志生成新文件
        if (localDate == null) {
            localDate = LocalDate.now();
            if (new File(fileName).length() > 0) {
                rollOver = true;
            }
        }

        if (fileName != null && qw != null) {
            long size = ((CountingQuietWriter) qw).getCount();
            long nextRollover = 0;
            //添加日期判断,确保变更日期触发日志截断
            boolean flag = (size >= maxFileSize && size >= nextRollover) || !LocalDate.now().equals(localDate);
            if (flag) {
                localDate = LocalDate.now();
                rollOver = true;
            }
        }
        //如果存在换文件操作,就在换完文件后再输出日志
        if (rollOver) {
            setFile(parternFileName);
            rollOver();
        }
        super.subAppend(event);
    }


    /**
     * 路径带时间字符串格式化
     */
    static class DatePatternParser {
        static final String HEAD = "%d";

        static String parse(StringBuilder str) {
            while (str.indexOf(HEAD) > 0) {
                int index = str.indexOf(HEAD);
                int indexEnd = str.indexOf("}", index) + 1;
                int indexStart = str.indexOf("{", index);
                String p = str.substring(indexStart + 1, indexEnd - 1);
                SimpleDateFormat sdf = new SimpleDateFormat(p);
                str.replace(index, indexEnd, sdf.format(new Date()));
            }
            return str.toString().trim();
        }
    }
}


log4j.properties

# DEBUG < INFO < WARN < ERROR < FATAL
#log4j.rootLogger=ALL,debug,console,info,warn,error

logDir=./logs/jfinal-test
log4j.rootLogger=ALL,console,debug,info,warn,error

log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}|%t|%c|%p|%m%n
log4j.appender.console.Threshold = debug

log4j.logger.debug=debug
log4j.appender.debug=com.source.util.MyRollingFileAppender
log4j.appender.debug.layout=org.apache.log4j.PatternLayout
log4j.appender.debug.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}|%p|%m%n
log4j.appender.debug.Threshold = DEBUG
log4j.appender.debug.File=${logDir}/%d{yyyy-MM}/%d{dd}/debug/debug.log
log4j.appender.debug.MaxFileSize=10MB
log4j.appender.debug.MaxBackupIndex=10
log4j.appender.debug.Encoding =UTF-8

log4j.logger.info=info
log4j.appender.info=com.source.util.MyRollingFileAppender
log4j.appender.info.layout=org.apache.log4j.PatternLayout
log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}|%p|%m%n
log4j.appender.info.Threshold = INFO
log4j.appender.info.File=${logDir}/%d{yyyy-MM}/%d{dd}/info/info.log
log4j.appender.info.MaxFileSize=10MB
log4j.appender.info.MaxBackupIndex=10
log4j.appender.info.Encoding =UTF-8

log4j.logger.warn=warn
log4j.appender.warn=com.source.util.MyRollingFileAppender
log4j.appender.warn.layout=org.apache.log4j.PatternLayout
log4j.appender.warn.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}|%p|%m%n
log4j.appender.warn.Threshold = WARN
log4j.appender.warn.File=${logDir}/%d{yyyy-MM}/%d{dd}/warn/warn.log
log4j.appender.warn.MaxFileSize=10MB
log4j.appender.warn.MaxBackupIndex=10
log4j.appender.warn.Encoding =UTF-8

log4j.logger.error=error
log4j.appender.error=com.source.util.MyRollingFileAppender
log4j.appender.error.layout=org.apache.log4j.PatternLayout
log4j.appender.error.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}|%p|%m%n
log4j.appender.error.Threshold = ERROR
log4j.appender.error.File=${logDir}/%d{yyyy-MM}/%d{dd}/error/error.log
log4j.appender.error.MaxFileSize=10MB
log4j.appender.error.MaxBackupIndex=10
log4j.appender.error.Encoding =UTF-8


评论区

zzutligang

2020-04-01 11:00

支持!

JFinal

2020-04-01 17:37

这个分享很实用,日志按日期划分便于查看与管理,将来写脚本来分析也很方便

fred

2020-04-01 21:42

最好能设置,只保留N天

sourceTT

2020-04-02 08:47

@fred 这个只是对RollingFileAppender的输出文件进行切换,它自己没有对历史目录的日志文件的遍历,所以你说的删除最好自己写个定时任务实现。

chcode

2020-04-02 12:34

@sourceTT logback 和log4j2 可以实现定义策略自动删除 log4j没怎么用过不知道

sourceTT

2020-04-02 14:25

@chcode RollingFileAppender其实就是根据日志文件大小滚动的默认实现,单个目录下是会自动删除的,就是又要实现根据日志文件大小滚动删除还要根据日期进行滚动删除,不改扫描逻辑是无法实现的。

热门分享

扫码入社