序
本文主要研究一下rocketmq的DailyRollingFileAppender
DailyRollingFileAppender
org/apache/rocketmq/logging/inner/LoggingBuilder.java
public static class DailyRollingFileAppender extends FileAppender {
static final int TOP_OF_TROUBLE = -1;
static final int TOP_OF_MINUTE = 0;
static final int TOP_OF_HOUR = 1;
static final int HALF_DAY = 2;
static final int TOP_OF_DAY = 3;
static final int TOP_OF_WEEK = 4;
static final int TOP_OF_MONTH = 5;
/**
* The date pattern. By default, the pattern is set to
* "'.'yyyy-MM-dd" meaning daily rollover.
*/
private String datePattern = "'.'yyyy-MM-dd";
private String scheduledFilename;
private long nextCheck = System.currentTimeMillis() - 1;
Date now = new Date();
SimpleDateFormat sdf;
RollingCalendar rc = new RollingCalendar();
final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");
public void setDatePattern(String pattern) {
datePattern = pattern;
}
public String getDatePattern() {
return datePattern;
}
public void activateOptions() {
super.activateOptions();
if (datePattern != null && fileName != null) {
now.setTime(System.currentTimeMillis());
sdf = new SimpleDateFormat(datePattern);
int type = computeCheckPeriod();
printPeriodicity(type);
rc.setType(type);
File file = new File(fileName);
scheduledFilename = fileName + sdf.format(new Date(file.lastModified()));
} else {
SysLogger.error("Either File or DatePattern options are not set for appender [" + name + "].");
}
}
void printPeriodicity(int type) {
switch (type) {
case TOP_OF_MINUTE:
SysLogger.debug("Appender [" + name + "] to be rolled every minute.");
break;
case TOP_OF_HOUR:
SysLogger.debug("Appender [" + name + "] to be rolled on top of every hour.");
break;
case HALF_DAY:
SysLogger.debug("Appender [" + name + "] to be rolled at midday and midnight.");
break;
case TOP_OF_DAY:
SysLogger.debug("Appender [" + name + "] to be rolled at midnight.");
break;
case TOP_OF_WEEK:
SysLogger.debug("Appender [" + name + "] to be rolled at start of week.");
break;
case TOP_OF_MONTH:
SysLogger.debug("Appender [" + name + "] to be rolled at start of every month.");
break;
default:
SysLogger.warn("Unknown periodicity for appender [" + name + "].");
}
}
int computeCheckPeriod() {
RollingCalendar rollingCalendar = new RollingCalendar(gmtTimeZone, Locale.getDefault());
// set sate to 1970-01-01 00:00:00 GMT
Date epoch = new Date(0);
if (datePattern != null) {
for (int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
simpleDateFormat.setTimeZone(gmtTimeZone);
String r0 = simpleDateFormat.format(epoch);
rollingCalendar.setType(i);
Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
String r1 = simpleDateFormat.format(next);
if (r0 != null && r1 != null && !r0.equals(r1)) {
return i;
}
}
}
return TOP_OF_TROUBLE;
}
void rollOver() throws IOException {
if (datePattern == null) {
handleError("Missing DatePattern option in rollOver().");
return;
}
String datedFilename = fileName + sdf.format(now);
if (scheduledFilename.equals(datedFilename)) {
return;
}
this.closeFile();
File target = new File(scheduledFilename);
if (target.exists() && !target.delete()) {
SysLogger.error("Failed to delete [" + scheduledFilename + "].");
}
File file = new File(fileName);
boolean result = file.renameTo(target);
if (result) {
SysLogger.debug(fileName + " -> " + scheduledFilename);
} else {
SysLogger.error("Failed to rename [" + fileName + "] to [" + scheduledFilename + "].");
}
try {
this.setFile(fileName, true, this.bufferedIO, this.bufferSize);
} catch (IOException e) {
handleError("setFile(" + fileName + ", true) call failed.");
}
scheduledFilename = datedFilename;
}
protected void subAppend(LoggingEvent event) {
long n = System.currentTimeMillis();
if (n >= nextCheck) {
now.setTime(n);
nextCheck = rc.getNextCheckMillis(now);
try {
rollOver();
} catch (IOException ioe) {
if (ioe instanceof InterruptedIOException) {
Thread.currentThread().interrupt();
}
SysLogger.error("rollOver() failed.", ioe);
}
}
super.subAppend(event);
}
}
- 这里重写了subAppend方法,先检查当前时间是否大于nextCheck值,大于则更新nextCheck值,然后进行rollOver操作,最后在调用父类的subAppend方法
- rollOver方法先检查datedFilename是否等于scheduledFilename,如果不等则进行重命名操作,然后调用FileAppender的setFile操作,最后更新scheduledFilename值
小结
- rocketmq的DailyRollingFileAppender的实现是重写subAppend,每次subAppend之前先检查是否需要重命名文件,如果需要则调用rollOver方法
- rollOver方法主要是将文件名重名为scheduledFilename,datePattern的格式为.yyyy-MM-dd