log4j如何设置只保留N天日志呢?

乔欣 Java经验 发布时间:2023-03-14 21:54:40 阅读数:13084 1
下文笔者讲述log4j设置只保留指定天数日志的方法分享,如下所示
log4j保留指定天数的实现思路:
     只需重写的org.apache.log4j.DailyRollingFileAppender源码
	 即可实现保留指定天数的日志
例:编写相应的实现代码
public class CustomDailyRollingFileAppender 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;
 
	/**
	 * 默认设置:"'.'yyyy-MM-dd"
	 * 设置说明:按天循环打印日志
	 */
	private String datePattern = "'.'yyyy-MM-dd";
 
	private int  maxBackupIndex  = 1;
 
	private String scheduledFilename;
 
	/**
	 The next time we estimate a rollover should occur. */
	private long nextCheck = System.currentTimeMillis () - 1;
 
	Date now = new Date();
 
	SimpleDateFormat sdf;
 
	RollingCalendar rc = new RollingCalendar();
 
	int checkPeriod = TOP_OF_TROUBLE;
 
	/**
	 * 获取当前环境所处的时区
	 * 仅供computeCheckPeriod方法使用
	 */
	static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");
 
	public CustomDailyRollingFileAppender() {}
 
	public CustomDailyRollingFileAppender(Layout layout, String filename, String datePattern) throws IOException {
		super(layout, filename, true);
 
		this.datePattern = datePattern;
		activateOptions();
	}
 
	public void setDatePattern(String pattern) {
		this.datePattern = pattern;
	}
 
	public String getDatePattern() {
		return datePattern;
	}
 
	public int getMaxBackupIndex() {
		return maxBackupIndex;
	}
 
	public void setMaxBackupIndex(int maxBackupIndex) {
		this.maxBackupIndex = maxBackupIndex;
	}
 
	/**
	 * activateOptions译名为激活操作
	 * 意思是按照配置的参数进行初始化
	 * scheduledFilename为log的最后一次修改时间
	 */
	@Override
	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 {
			LogLog.error("Either File or DatePattern options are not set for appender ["+name+"].");
		}
	}
 
	/**
	 * 根据type打印做出日志打印
	 * @param type
	 */
	void printPeriodicity(int type) {
		switch(type) {
			case TOP_OF_MINUTE:
				LogLog.debug("Appender ["+name+"] to be rolled every minute.");
				break;
			case TOP_OF_HOUR:
				LogLog.debug("Appender ["+name+"] to be rolled on top of every hour.");
				break;
			case HALF_DAY:
				LogLog.debug("Appender ["+name+"] to be rolled at midday and midnight.");
				break;
			case TOP_OF_DAY:
				LogLog.debug("Appender ["+name+"] to be rolled at midnight.");
				break;
			case TOP_OF_WEEK:
				LogLog.debug("Appender ["+name+"] to be rolled at start of week.");
				break;
			case TOP_OF_MONTH:
				LogLog.debug("Appender ["+name+"] to be rolled at start of every month.");
				break;
			default:
				LogLog.warn("Unknown periodicity for appender ["+name+"].");
		}
	}
 
 
//   This method computes the roll over period by looping over the
//   periods, starting with the shortest, and stopping when the r0 is
//   different from from r1, where r0 is the epoch formatted according
//   the datePattern (supplied by the user) and r1 is the
//   epoch+nextMillis(i) formatted according to datePattern. All date
//   formatting is done in GMT and not local format because the test
//   logic is based on comparisons relative to 1970-01-01 00:00:00
//   GMT (the epoch).
 
	int computeCheckPeriod() {
		RollingCalendar rollingCalendar = new RollingCalendar(gmtTimeZone, Locale.getDefault());
		//设置初始时间为格林尼治时间: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);
				//System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1);
				if(r0 != null && r1 != null && !r0.equals(r1)) {
					return i;
				}
			}
		}
		return TOP_OF_TROUBLE; // Deliberately head for trouble...
	}
 
	/**
	 * 按照周期将当前日志文件转存为日期文件
	 *
	 * @throws IOException
	 */
	void rollOver() throws IOException {
 
		if (datePattern == null) {
			errorHandler.error("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();
		}
 
		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 (file.getParentFile().exists()){
			File[] files = file.getParentFile().listFiles(new LogFileFilter(file.getName()));
			Long[] dateArray = new Long[files.length];
			for (int i = 0; i < files.length; i++) {
				File fileItem = files[i];
				String fileDateStr = fileItem.getName().replace(file.getName(), "");
				Date filedate = null;
				try {
					filedate = sdf.parse(fileDateStr);
					long fileDateLong = filedate.getTime();
					dateArray[i] = fileDateLong;
				} catch (ParseException e) {
					LogLog.error("Parse File Date Throw Exception : " + e.getMessage());
				}
			}
			Arrays.sort(dateArray);
			if (dateArray.length > maxBackupIndex) {
				for (int i = 0; i < dateArray.length - maxBackupIndex; i++) {
					String dateFileName = file.getPath() + sdf.format(dateArray[i]);
					File dateFile = new File(dateFileName);
					if (datefile.exists()) {
						dateFile.delete();
					}
				}
			}
		}
 
		try {
			// This will also close the file. This is OK since multiple close operations are safe.
			this.setFile(fileName, true, this.bufferedIO, this.bufferSize);
		}
		catch(IOException e) {
			errorHandler.error("setFile("+fileName+", true) call failed.");
		}
		scheduledFilename = datedFilename;
	}
 
	/**
	 * 写入日志之前判断是否需要新起一个日志来记录
	 */
	@Override
	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();
				}
				LogLog.error("rollOver() failed.", ioe);
			}
		}
		super.subAppend(event);
	}
}
 
/**
 * 文件过滤器
 */
class LogFileFilter implements FileFilter {
	private String logName;
 
	public LogFileFilter(String logName) {
		this.logName = logName;
	}
 
	@Override
	public boolean accept(File file) {
		if (logName == null || file.isDirectory()) {
			return false;
		} else {
			LogLog.debug(file.getName());
			return file.getName().startsWith(logName);
		}
	}
}
 
/**
 * CustomDailyRollingFileAppender的内部类
 * 提供周期类型和当前时间 ,计算并返回下一个周期的开始时间
 */
class RollingCalendar extends GregorianCalendar {
	private static final long serialVersionUID = -3560331770601814177L;
 
	int type = CustomDailyRollingFileAppender.TOP_OF_TROUBLE;
 
	/**
	 * RollingCalendar默认构造器
	 */
	RollingCalendar() {
		super();
	}
 
	/**
	 * RollingCalendar构造器
	 * 根据地点时区 ,获取对应的日历Calendar
	 * @param tz
	 * @param locale
	 */
	RollingCalendar(TimeZone tz, Locale locale) {
		super(tz, locale);
	}
 
	void setType(int type) {
		this.type = type;
	}
 
	public long getNextCheckMillis(Date now) {
		return getNextCheckDate(now).getTime();
	}
 
	/**
	 * 根据所传入的时间以及时间类型获取下一个时间
	 * @param now
	 * @return
	 */
	public Date getNextCheckDate(Date now) {
		this.setTime(now);
 
		switch(type) {
			case CustomDailyRollingFileAppender.TOP_OF_MINUTE:
				this.set(Calendar.SECOND, 0);
				this.set(Calendar.MILLISECOND, 0);
				this.add(Calendar.MINUTE, 1);
				break;
			case CustomDailyRollingFileAppender.TOP_OF_HOUR:
				this.set(Calendar.MINUTE, 0);
				this.set(Calendar.SECOND, 0);
				this.set(Calendar.MILLISECOND, 0);
				this.add(Calendar.HOUR_OF_DAY, 1);
				break;
			case CustomDailyRollingFileAppender.HALF_DAY:
				this.set(Calendar.MINUTE, 0);
				this.set(Calendar.SECOND, 0);
				this.set(Calendar.MILLISECOND, 0);
				int hour = get(Calendar.HOUR_OF_DAY);
				if(hour < 12) {
					this.set(Calendar.HOUR_OF_DAY, 12);
				} else {
					this.set(Calendar.HOUR_OF_DAY, 0);
					this.add(Calendar.DAY_OF_MONTH, 1);
				}
				break;
			case CustomDailyRollingFileAppender.TOP_OF_DAY:
				this.set(Calendar.HOUR_OF_DAY, 0);
				this.set(Calendar.MINUTE, 0);
				this.set(Calendar.SECOND, 0);
				this.set(Calendar.MILLISECOND, 0);
				this.add(Calendar.DATE, 1);
				break;
			case CustomDailyRollingFileAppender.TOP_OF_WEEK:
				this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek());
				this.set(Calendar.HOUR_OF_DAY, 0);
				this.set(Calendar.MINUTE, 0);
				this.set(Calendar.SECOND, 0);
				this.set(Calendar.MILLISECOND, 0);
				this.add(Calendar.WEEK_OF_YEAR, 1);
				break;
			case CustomDailyRollingFileAppender.TOP_OF_MONTH:
				this.set(Calendar.DATE, 1);
				this.set(Calendar.HOUR_OF_DAY, 0);
				this.set(Calendar.MINUTE, 0);
				this.set(Calendar.SECOND, 0);
				this.set(Calendar.MILLISECOND, 0);
				this.add(Calendar.MONTH, 1);
				break;
			default:
				throw new IllegalStateException("Unknown periodicity type.");
		}
		return getTime();
	}
}
//配置相应的循环周期 log4j.properties文件
log4j.rootLogger=DEBUG,D,consol
 
log4j.appender.consol=org.apache.log4j.ConsoleAppender
log4j.appender.consol.layout=org.apache.log4j.PatternLayout
log4j.appender.consol.Threshold = debug
log4j.appender.consol.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} - [ %p ]  %m%n
# com.java265.util.CustomDailyRollingFileAppender
# org.apache.log4j.DailyRollingFileAppender
log4j.appender.D = com.java265.util.CustomDailyRollingFileAppender
log4j.appender.D.File =${user.dir}/../logs/ctg_applog_.log
log4j.appender.D.datePattern = yyyy-MM-dd-HH'.'
log4j.appender.D.maxBackupIndex=48
log4j.appender.D.Append = true
log4j.appender.D.Threshold = info
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern =%-d{yyyyMMddHHmmss:S}%m%n
 
log4j.logger.org.springframework=WARN
log4j.logger.com.ctg=info
log4j.logger.org.apache=WARN
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG


maxBackupIndex就是保留多少个文件,
//我是按照每小时进行生成一个文件
//48 小时则对应4天--保留4天日志
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaJingYan/202303/16788021406041.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者