扩展的一个按天滚动的appender类 暂时不支持datePattern设置,但是可以配置maxBackupIndex,该源代码来自网上,因为需要生成动态日志,做了一点点扩展.
log4j.properties
log4j.rootLogger=info,stdout,file
log4j.logger.org=info
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file hibernate.log ###
log4j.appender.file=com.dmx.log4jext.DayRollingFileAppender
log4j.appender.file.File=/opt/logs/log.log
log4j.appender.file.vmProperty=weblogic.Name
log4j.appender.file.maxBackupIndex=7
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{HH\:mm\:ss} %-5p [%t] (%13F\:%L) %3x - %m%n
java代码:
package com.dmx.log4jext;
import org.apache.log4j.FileAppender;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Layout;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.LoggingEvent;
/**
* 扩展的一个按天滚动的appender类 暂时不支持datePattern设置,但是可以配置maxBackupIndex
*/
public class DayRollingFileAppender extends FileAppender {
// 不允许改写的datepattern
private final String datePattern = "'.'yyyy-MM-dd";
// 最多文件增长个数
private int maxBackupIndex = 2;
// 文件名+上次最后更新时间
private String scheduledFilename;
// 系统参数属性 根据系统属性动态生成日志文件名
private String vmProperty;
// The next time we estimate a rollover should occur
private long nextCheck = System.currentTimeMillis() - 1;
Date now = new Date();
SimpleDateFormat sdf;
public DayRollingFileAppender() {
}
public DayRollingFileAppender(Layout layout, String vmProperty,
String filename, int maxBackupIndex) throws IOException {
super(layout, filename, true);
this.vmProperty = vmProperty;
this.maxBackupIndex = maxBackupIndex;
activateOptions();
}
/**
* 初始化本Appender对象的时候调用一次
*/
public void activateOptions() {
super.activateOptions();
if (fileName != null) { // perf.log
now.setTime(System.currentTimeMillis());
sdf = new SimpleDateFormat(datePattern);
File file = new File(fileName);
// 获取最后更新时间拼成的文件名
scheduledFilename = fileName
+ sdf.format(new Date(file.lastModified()));
} else {
LogLog.error("File is not set for appender [" + name + "].");
}
if (maxBackupIndex <= 0) {
LogLog.error("maxBackupIndex reset to default value[2],orignal value is:"
+ maxBackupIndex);
maxBackupIndex = 2;
}
}
/**
* 滚动文件的函数: 1.对文件名带的时间戳进行比较,确定是否更新 2.if需要更新,当前文件rename到文件名+日期, 重新开始写文件
* 3.针对配置的maxBackupIndex,删除过期的文件
*/
void rollOver() throws IOException {
String datedFilename = fileName + sdf.format(now);
// 如果上次写的日期跟当前日期相同,不需要换文件
if (scheduledFilename.equals(datedFilename)) {
return;
}
// close current file, and rename it to datedFilename
this.closeFile();
File target = new File(scheduledFilename);
if (target.exists()) {
target.delete();
}
File file = new File(fileName);
boolean result = file.renameTo(target);
if (result) {
LogLog.debug(fileName + " -> " + scheduledFilename);
} else {
LogLog.error("Failed to rename [" + fileName + "] to ["
+ scheduledFilename + "].");
}
// 删除过期文件
if (maxBackupIndex > 0) {
File folder = new File(file.getParent());
List<String> maxBackupIndexDates = getMaxBackupIndexDates();
for (File ff : folder.listFiles()) { // 遍历目录,将日期不在备份范围内的日志删掉
if (ff.getName().startsWith(file.getName())
&& !ff.getName().equals(file.getName())) {
// 获取文件名带的日期时间戳
String markedDate = ff.getName().substring(
file.getName().length());
if (!maxBackupIndexDates.contains(markedDate)) {
result = ff.delete();
}
if (result) {
LogLog.debug(ff.getName() + " ->deleted ");
} else {
LogLog.error("Failed to deleted old DayRollingFileAppender file :"
+ ff.getName());
}
}
}
}
try {
// This will also close the file. This is OK since multiple
// close operations are safe.
this.setFile(fileName, false, this.bufferedIO, this.bufferSize);
} catch (IOException e) {
errorHandler.error("setFile(" + fileName + ", false) call failed.");
}
scheduledFilename = datedFilename; // 更新最后更新日期戳
}
/**
* Actual writing occurs here. 这个方法是写操作真正的执行过程!
*/
protected void subAppend(LoggingEvent event) {
long n = System.currentTimeMillis();
if (n >= nextCheck) { // 在每次写操作前判断一下是否需要滚动文件
now.setTime(n);
nextCheck = getNextDayCheckPoint(now);
try {
rollOver();
} catch (IOException ioe) {
LogLog.error("rollOver() failed.", ioe);
}
}
super.subAppend(event);
}
/**
* 获取下一天的时间变更点
*
* @param now
* @return
*/
long getNextDayCheckPoint(Date now) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(now);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);// 注意MILLISECOND,毫秒也要置0.。。否则错了也找不出来的
calendar.add(Calendar.DATE, 1);
return calendar.getTimeInMillis();
}
/**
* 根据maxBackupIndex配置的备份文件个数,获取要保留log文件的日期范围集合
*
* @return list<'fileName+yyyy-MM-dd'>
*/
List<String> getMaxBackupIndexDates() {
List<String> result = new ArrayList<String>();
if (maxBackupIndex > 0) {
for (int i = 1; i <= maxBackupIndex; i++) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(now);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);// 注意MILLISECOND,毫秒也要置0.。。否则错了也找不出来的
calendar.add(Calendar.DATE, -i);
result.add(sdf.format(calendar.getTime()));
}
}
return result;
}
public int getMaxBackupIndex() {
return maxBackupIndex;
}
public void setMaxBackupIndex(int maxBackupIndex) {
this.maxBackupIndex = maxBackupIndex;
}
public String getDatePattern() {
return datePattern;
}
public String getVmProperty() {
return vmProperty;
}
public void setVmProperty(String vmProperty) {
this.vmProperty = vmProperty;
// 改变fileName的值
if (null != vmProperty && !"".equals(vmProperty)) { // if-one
// 从jvm中获取系统参数
String vmValue = System.getProperty(vmProperty);
if (vmValue != null && !"".equals(vmValue)) {// if-two
fileName = this.parseFile(fileName, vmValue);
}// end if-two
}// end if-one
}
private String parseFile(String str, String parseStr) {
if (str != null && !"".equals(str) && parseStr != null
&& !"".equals(parseStr)) {
// 对配置文件中的File进行解析看是否带有路径
String tempStr = str.replaceAll("\\/", "@").replaceAll("\\\\", "@");
// String[] strArr = str.split("\\/").length>0 ? str.split("\\/") :
// str.split("\\\\");
String[] strArr = tempStr.split("@");
String temp = parseStr + "-" + strArr[strArr.length - 1];
str = str.replace(strArr[strArr.length - 1], temp);
return str;
} else {
return str;
}
}
public static void main(String[] args) {
DayRollingFileAppender aa = new DayRollingFileAppender();
String path = "E:\\opt\\apps\\log\\portal-vpg.log";
path = "/opt/apps/logs/portal-vpg.log";
String bb = aa.parseFile(path, "dianbo113");
System.out.println(bb);
}
}