继承FileAppender,将log文件进行日常转存。我们常用的日志处理类,官方注释里说已证实有并发和数据丢失的问题,可惜我看不出来...
可以自定义转存日期表达式datePattern(格式需遵循SimpleDateFormat的约定),如
'.'yyyy-MM
'.'yyyy-ww
'.'yyyy-MM-dd
'.'yyyy-MM-dd-a
'.'yyyy-MM-dd-HH
'.'yyyy-MM-dd-HH-mm
注意不要包含任何冒号
它根据用户提供的日期表达式datePattern,通过内部类RollingCalendar计算得到对应的日期检查周期rc.type,每次log输出之前,计算下次检查时间nextCheck,对比当前时间,判断是否进行文件转存。
主要方法有
//各级检查周期对应的常量
// The code assumes that the following constants are in a increasing sequence.
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;
//初始化配置项
public void activateOptions() {
super.activateOptions();
if(datePattern != null && fileName != null) {
now.setTime(System.currentTimeMillis());
sdf = new SimpleDateFormat(datePattern);
int type = computeCheckPeriod();//计算datePattern对应的检查周期
printPeriodicity(type);//打印当前检查周期
rc.setType(type);//内部RollingCalendar会在log输出之前根据type计算出下次检查时间
File file = new File(fileName);//log输出文件名
scheduledFilename = fileName+sdf.format(new Date(file.lastModified()));//log转存文件名
} else {
LogLog.error("Either File or DatePattern options are not set 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 DateFormat = new SimpleDateFormat(datePattern);
DateFormat.setTimeZone(gmtTimeZone); // do all date formatting in GMT
String r0 = DateFormat.format(epoch);
rollingCalendar.setType(i);
Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
String r1 = DateFormat.format(next);
//r0、r1均以datePattern格式来转换日期,若type小于datePattern表示的最小范围,对应日期next的变化不会影响格式化后的r1的值
//每循环一次,type(也就是i) 增1,最终得到的type就是datePattern表示的最小范围
if(r0 != null && r1 != null && !r0.equals(r1)) {
return i;
}
}
}
return TOP_OF_TROUBLE; // Deliberately head for trouble...
}
//log输出
protected void subAppend(LoggingEvent event) {
//在每次调用父类subAppend方法输出文件之前,进行周期计算
//若当前时间晚于'检查点时间',调用rollOver()方法进行日志转存,将当前log文件转存为指定日期结尾的文件,然后将父类的QuietWriter指向新的log文件
//当然在转存之前,需要再次计算并刷新'检查点时间',rc内部type会影响计算结果(在初始化配置时已根据datePattern计算得到)
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();
}
LogLog.error("rollOver() failed.", ioe);
}
}
super.subAppend(event);
}
同样继承于FileAppender,由文件大小来转存log文件
继承于RollingFileAppender,通过Socket转存消息来进行转存操作,后台运行着一个Socket线程,每次收到转存消息,会新起一个线程进行日志转存,并将转存结果信息返回。
只是介绍了关键的一些类,但他们的生命周期,相关的属性类和辅助类还没提到,主要是Filter和Layout,下次再更新。fileappender rollover
还有上面几个关键方法中的同步关键字,我还没搞懂应该怎么解释。fileappender rollover
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-32111-3.html
绝大多数的人都不理解谢教授的真正用意
但没人说淘宝卖的都是假的
后一条慢慢来