序
本文主要研究一下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ülcü
*/
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ülcü
*/
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,其中还配合压缩模式进行压缩处理。