聊聊logback的FixedWindowRollingPolicy

本文主要研究一下logback的FixedWindowRollingPolicy

RollingPolicy

ch/qos/logback/core/rolling/RollingPolicy.java

复制代码
/**
 * A <code>RollingPolicy</code> is responsible for performing the rolling over
 * of the active log file. The <code>RollingPolicy</code> is also responsible
 * for providing the <em>active log file</em>, that is the live file where
 * logging output will be directed.
 * 
 * @author Ceki G&uuml;lc&uuml;
 */
public interface RollingPolicy extends LifeCycle {

    /**
     * Rolls over log files according to implementation policy.
     * 
     * <p>
     * This method is invoked by {@link RollingFileAppender}, usually at the behest
     * of its {@link TriggeringPolicy}.
     * 
     * @throws RolloverFailure Thrown if the rollover operation fails for any
     *                         reason.
     */
    void rollover() throws RolloverFailure;

    /**
     * Get the name of the active log file.
     * 
     * <p>
     * With implementations such as {@link TimeBasedRollingPolicy}, this method
     * returns a new file name, where the actual output will be sent.
     * 
     * <p>
     * On other implementations, this method might return the FileAppender's file
     * property.
     */
    String getActiveFileName();

    /**
     * The compression mode for this policy.
     * 
     * @return
     */
    CompressionMode getCompressionMode();

    /**
     * This method allows RollingPolicy implementations to be aware of their
     * containing appender.
     * 
     * @param appender
     */

    void setParent(FileAppender<?> appender);
}

RollingPolicy接口定义了rollover、getActiveFileName、getCompressionMode、setParent方法

RollingPolicyBase

ch/qos/logback/core/rolling/RollingPolicyBase.java

复制代码
/**
 * Implements methods common to most, it not all, rolling policies. Currently
 * such methods are limited to a compression mode getter/setter.
 * 
 * @author Ceki G&uuml;lc&uuml;
 */
public abstract class RollingPolicyBase extends ContextAwareBase implements RollingPolicy {
    protected CompressionMode compressionMode = CompressionMode.NONE;

    FileNamePattern fileNamePattern;
    // fileNamePatternStr is always slashified, see setter
    protected String fileNamePatternStr;

    private FileAppender<?> parent;

    // use to name files within zip file, i.e. the zipEntry
    FileNamePattern zipEntryFileNamePattern;
    private boolean started;

    /**
     * Given the FileNamePattern string, this method determines the compression mode
     * depending on last letters of the fileNamePatternStr. Patterns ending with .gz
     * imply GZIP compression, endings with '.zip' imply ZIP compression. Otherwise
     * and by default, there is no compression.
     * 
     */
    protected void determineCompressionMode() {
        if (fileNamePatternStr.endsWith(".gz")) {
            addInfo("Will use gz compression");
            compressionMode = CompressionMode.GZ;
        } else if (fileNamePatternStr.endsWith(".zip")) {
            addInfo("Will use zip compression");
            compressionMode = CompressionMode.ZIP;
        } else {
            addInfo("No compression will be used");
            compressionMode = CompressionMode.NONE;
        }
    }

    //......
}    

RollingPolicyBase定义了compressionMode、fileNamePattern、fileNamePatternStr、parent、zipEntryFileNamePattern、started;

determineCompressionMode方法会根据fileNamePatternStr的后缀来判断,默认支持gz、zip

FixedWindowRollingPolicy

ch/qos/logback/core/rolling/FixedWindowRollingPolicy.java

复制代码
public class FixedWindowRollingPolicy extends RollingPolicyBase {
    static final String FNP_NOT_SET = "The \"FileNamePattern\" property must be set before using FixedWindowRollingPolicy. ";
    static final String PRUDENT_MODE_UNSUPPORTED = "See also " + CODES_URL + "#tbr_fnp_prudent_unsupported";
    static final String SEE_PARENT_FN_NOT_SET = "Please refer to " + CODES_URL + "#fwrp_parentFileName_not_set";
    int maxIndex;
    int minIndex;
    RenameUtil util = new RenameUtil();
    Compressor compressor;

    public static final String ZIP_ENTRY_DATE_PATTERN = "yyyy-MM-dd_HHmm";

    /**
     * It's almost always a bad idea to have a large window size, say over 20.
     */
    private static int MAX_WINDOW_SIZE = 20;

    public FixedWindowRollingPolicy() {
        minIndex = 1;
        maxIndex = 7;
    }

    //......
}    

FixedWindowRollingPolicy继承了RollingPolicyBase,他定义了minIndex、maxIndex、compressor属性

start

复制代码
    public void start() {
        util.setContext(this.context);

        if (fileNamePatternStr != null) {
            fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context);
            determineCompressionMode();
        } else {
            addError(FNP_NOT_SET);
            addError(CoreConstants.SEE_FNP_NOT_SET);
            throw new IllegalStateException(FNP_NOT_SET + CoreConstants.SEE_FNP_NOT_SET);
        }

        if (isParentPrudent()) {
            addError("Prudent mode is not supported with FixedWindowRollingPolicy.");
            addError(PRUDENT_MODE_UNSUPPORTED);
            throw new IllegalStateException("Prudent mode is not supported.");
        }

        if (getParentsRawFileProperty() == null) {
            addError("The File name property must be set before using this rolling policy.");
            addError(SEE_PARENT_FN_NOT_SET);
            throw new IllegalStateException("The \"File\" option must be set.");
        }

        if (maxIndex < minIndex) {
            addWarn("MaxIndex (" + maxIndex + ") cannot be smaller than MinIndex (" + minIndex + ").");
            addWarn("Setting maxIndex to equal minIndex.");
            maxIndex = minIndex;
        }

        final int maxWindowSize = getMaxWindowSize();
        if ((maxIndex - minIndex) > maxWindowSize) {
            addWarn("Large window sizes are not allowed.");
            maxIndex = minIndex + maxWindowSize;
            addWarn("MaxIndex reduced to " + maxIndex);
        }

        IntegerTokenConverter itc = fileNamePattern.getIntegerTokenConverter();

        if (itc == null) {
            throw new IllegalStateException(
                    "FileNamePattern [" + fileNamePattern.getPattern() + "] does not contain a valid IntegerToken");
        }

        if (compressionMode == CompressionMode.ZIP) {
            String zipEntryFileNamePatternStr = transformFileNamePatternFromInt2Date(fileNamePatternStr);
            zipEntryFileNamePattern = new FileNamePattern(zipEntryFileNamePatternStr, context);
        }
        compressor = new Compressor(compressionMode);
        compressor.setContext(this.context);
        super.start();
    }

start方法先根据fileNamePattern来创建FileNamePattern,然后判断压缩模式,然后校验minIndex及maxIndex,要求相差不能超过MAX_WINDOW_SIZE(默认值为20),之后判断如果是zip模式的则创建zipEntryFileNamePattern,最后根据压缩模式创建compressor

rollover

复制代码
    public void rollover() throws RolloverFailure {

        // Inside this method it is guaranteed that the hereto active log file is
        // closed.
        // If maxIndex <= 0, then there is no file renaming to be done.
        if (maxIndex >= 0) {
            // Delete the oldest file, to keep Windows happy.
            File file = new File(fileNamePattern.convertInt(maxIndex));

            if (file.exists()) {
                file.delete();
            }

            // Map {(maxIndex - 1), ..., minIndex} to {maxIndex, ..., minIndex+1}
            for (int i = maxIndex - 1; i >= minIndex; i--) {
                String toRenameStr = fileNamePattern.convertInt(i);
                File toRename = new File(toRenameStr);
                // no point in trying to rename a nonexistent file
                if (toRename.exists()) {
                    util.rename(toRenameStr, fileNamePattern.convertInt(i + 1));
                } else {
                    addInfo("Skipping roll-over for inexistent file " + toRenameStr);
                }
            }

            // move active file name to min
            switch (compressionMode) {
            case NONE:
                util.rename(getActiveFileName(), fileNamePattern.convertInt(minIndex));
                break;
            case GZ:
                compressor.compress(getActiveFileName(), fileNamePattern.convertInt(minIndex), null);
                break;
            case ZIP:
                compressor.compress(getActiveFileName(), fileNamePattern.convertInt(minIndex),
                        zipEntryFileNamePattern.convert(new Date()));
                break;
            }
        }
    }

rollover方法从maxIndex-1开始到minIndex,把这些文件名的序号加1,之后根据压缩模式判断,如果不压缩则把当前文件名重名为minIndex,若是gz压缩则把当前文件压缩然后命名为minIndex,若是zip压缩则把当前文件压缩然后命名为minIndex加上日期

小结

logback的FixedWindowRollingPolicy继承了RollingPolicyBase,实现了RollingPolicy接口,该接口定义了rollover、getActiveFileName、getCompressionMode、setParent方法,其中FixedWindowRollingPolicy的rollover的实现是根据minIndex及maxIndex来的,要求maxIndex及minIndex相差不能超过20,rollover的时候从maxIndex-1开始到minIndex,把这些文件名的序号加1,然后当前文件重命名为minIndex,其中还配合压缩模式进行压缩处理。

相关推荐
时见先生6 小时前
Python库和conda搭建虚拟环境
开发语言·人工智能·python·自然语言处理·conda
a努力。6 小时前
国家电网Java面试被问:混沌工程在分布式系统中的应用
java·开发语言·数据库·git·mysql·面试·职场和发展
Yvonne爱编码6 小时前
Java 四大内部类全解析:从设计本质到实战应用
java·开发语言·python
wqwqweee7 小时前
Flutter for OpenHarmony 看书管理记录App实战:搜索功能实现
开发语言·javascript·python·flutter·harmonyos
yongui478347 小时前
基于MATLAB的NALM锁模光纤激光器仿真实现
开发语言·matlab
-To be number.wan8 小时前
Python数据分析:numpy数值计算基础
开发语言·python·数据分析
Cx330❀9 小时前
【优选算法必刷100题】第038题(位运算):消失的两个数字
开发语言·c++·算法·leetcode·面试
Loo国昌9 小时前
深入理解 FastAPI:Python高性能API框架的完整指南
开发语言·人工智能·后端·python·langchain·fastapi
hoiii18710 小时前
16APSK/32APSK调制解调MATLAB仿真实现
开发语言·matlab·fpga开发
feifeigo12310 小时前
基于MATLAB的情感语音模板培训与识别实现方案
开发语言·matlab