Log4j扩展的一个按天滚动的appender类,同时支持动态日志
扩展的一个按天滚动的appender类 暂时不支持datePattern设置,但是可以配置maxBackupIndex,该源代码来自网上,因为需要生成动态日志,做了一点点扩展.
log4j.properties?
log4j.rootLogger=info,stdout,filelog4j.logger.org=info### direct log messages to stdout ###log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.Target=System.outlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n### direct messages to file hibernate.log ###log4j.appender.file=com.dmx.log4jext.DayRollingFileAppenderlog4j.appender.file.File=/opt/logs/log.loglog4j.appender.file.vmProperty=weblogic.Namelog4j.appender.file.maxBackupIndex=7log4j.appender.file.layout=org.apache.log4j.PatternLayoutlog4j.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 {// 不允许改写的datepatternprivate final String datePattern = "'.'yyyy-MM-dd";// 最多文件增长个数private int maxBackupIndex = 2;// 文件名+上次最后更新时间private String scheduledFilename;// 系统参数属性 根据系统属性动态生成日志文件名private String vmProperty;// The next time we estimate a rollover should occurprivate 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.lognow.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 datedFilenamethis.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-twofileName = 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);}}?