Log4j按大小、日期生成gz壓縮檔案並刪除過期日誌
阿新 • • 發佈:2019-02-05
1、準備jar :log4j-1.2.17.jar,commons-logging-1.2.jar,這2個就可以了,其他關於日誌的jar包就不要加進來了,在優先順序上會有衝突。
2、定義一個類,繼承RollingFileAppender類,這個類是按照日誌大小滾動生成日誌,並把日誌編號。我就在這個類基礎上重新寫了其中的一些方法,加上日期和刪除功能,稍加改動就行了。
package com.hm.sage.bigdata.spark.log; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.zip.GZIPOutputStream; import org.apache.log4j.RollingFileAppender; import org.apache.log4j.helpers.CountingQuietWriter; import org.apache.log4j.helpers.LogLog; public class RoolingAndDateFileAppender extends RollingFileAppender { private String datePattern;//日期格式 private String dateStr = "";//檔案後面的日期 private String expirDays = "1";//保留最近幾天 private String isCleanLog = "true";//是否清日誌 private String maxIndex = "100";//一天最多幾個檔案 private File rootDir;//父目錄的抽象路徑名 private String gzFormat = "gz";//壓縮格式 /** * 設定日期格式 * * @param datePattern */ public void setDatePattern(String datePattern) { if (null != datePattern && !"".equals(datePattern)) { this.datePattern = datePattern; } } /** * 獲取日期格式 * * @return */ public String getDatePattern() { return this.datePattern; } public void rollOver() { //檔案後面的日期 dateStr = new SimpleDateFormat(this.datePattern).format(new Date(System.currentTimeMillis())); File target = null; File file = null; if (qw != null) { //得到寫入的位元組數 long size = ((CountingQuietWriter) this.qw).getCount(); LogLog.debug("rolling over count=" + size); } //預設情況下有一個備份檔案 LogLog.debug("maxBackupIndex=" + this.maxBackupIndex); //如果maxIndex<=0則不需命名 if (maxIndex != null && Integer.parseInt(maxIndex) > 0) { //logRecoed.log.2018-08-24.5 //刪除舊檔案 file = new File(this.fileName + '.' + dateStr + '.' + Integer.parseInt(this.maxIndex) + '.' + gzFormat); if (file.exists()) {//測試用這個抽象路徑名錶示的檔案或目錄是否存在。 //如果當天日誌達到最大設定數量,則刪除當天第一個日誌,其他日誌為尾號減一 Boolean boo = reLogNum(); if (!boo) { LogLog.debug("日誌滾動重新命名失敗!"); } } } //獲取當天日期檔案個數 int count = cleanLog(); //生成新檔案 //target=new File(fileName+"."+dateStr+"."+(count+1)); this.closeFile();//關閉先前開啟的檔案。 file = new File(fileName); //creat zip output stream to build zip file GZIPOutputStream gzout = null; FileInputStream fin = null; byte[] buf = new byte[1024]; //file -> gz try { fin = new FileInputStream(file); gzout = new GZIPOutputStream(new FileOutputStream(fileName + "." + dateStr + "." + (count + 1) + '.' + gzFormat)); int num; while ((num = fin.read(buf, 0, buf.length)) != -1) { gzout.write(buf, 0, num); } gzout.flush(); gzout.finish(); LogLog.debug(fileName + " -> " + fileName + "." + dateStr + "." + (count + 1) + '.' + gzFormat + " successful!"); } catch (IOException e) { LogLog.error("add gz file(" + fileName + "." + dateStr + "." + (count + 1) + '.' + gzFormat + ") failed."); } finally { try { if (gzout != null) { gzout.close(); } if (fin != null) fin.close(); } catch (IOException e) { LogLog.error("close Stream failed"); } } //delete old file file.delete(); //LogLog.debug("Renaming file"+file+"to"+target); //file.renameTo(target);//重新命名file檔案 try { setFile(this.fileName, false, this.bufferedIO, this.bufferSize); } catch (IOException e) { LogLog.error("setFile(" + this.fileName + ",false)call failed.", e); } } /** * 獲取當天日期檔案個數 * * @return */ public int cleanLog() { int count = 0;//記錄當天檔案個數 if (Boolean.parseBoolean(isCleanLog)) { File f = new File(fileName); //返回這個抽象路徑名的父目錄的抽象路徑名 rootDir = f.getParentFile(); //目錄中所有檔案。 File[] listFiles = rootDir.listFiles(); for (File file : listFiles) { if (file.getName().contains(dateStr)) { count = count + 1;//是當天日誌,則+1 } else { //不是當天日誌需要判斷是否到期刪除 if (Boolean.parseBoolean(isCleanLog)) { //清除過期日誌 String[] split = file.getName().split("\\\\")[0].split("\\."); //校驗日誌名字,並取出日期,判斷過期時間 if (split.length == 4 && isExpTime(split[2])) { file.delete(); } } } } } return count; } /** * 判斷過期時間 * * @param time * @return */ public Boolean isExpTime(String time) { SimpleDateFormat format = new SimpleDateFormat(this.datePattern); try { Date logTime = format.parse(time); Date nowTime = format.parse(format.format(new Date())); //算出日誌與當前日期相差幾天 int days = (int) (nowTime.getTime() - logTime.getTime()) / (1000 * 3600 * 24); if (Math.abs(days) >= Integer.parseInt(expirDays)) { return true; } else { return false; } } catch (Exception e) { LogLog.error(e.toString()); return false; } } /** * 如果當天日誌達到最大設定數量,則每次刪除尾號為1的日誌, * 其他日誌編號依次減去1,重新命名 * * @return */ public Boolean reLogNum() { boolean renameTo = false; File startFile = new File(this.fileName + '.' + dateStr + '.' + "1" + '.' + gzFormat); if (startFile.exists() && startFile.delete()) {//是否存並刪除 for (int i = 2; i <= Integer.parseInt(maxIndex); i++) { File target = new File(this.fileName + '.' + dateStr + '.' + (i - 1) + '.' + gzFormat); this.closeFile(); File file = new File(this.fileName + '.' + dateStr + '.' + i + '.' + gzFormat); renameTo = file.renameTo(target);//重新命名file檔案 } } return renameTo; } public String getDateStr() { return dateStr; } public void setDateStr(String dateStr) { this.dateStr = dateStr; } public String getExpirDays() { return expirDays; } public void setExpirDays(String expirDays) { this.expirDays = expirDays; } public String getIsCleanLog() { return isCleanLog; } public void setIsCleanLog(String isCleanLog) { this.isCleanLog = isCleanLog; } public String getMaxIndex() { return maxIndex; } public void setMaxIndex(String maxIndex) { this.maxIndex = maxIndex; } }
log4j.properties 配置檔案
log4j.rootLogger=ALL,R,CONSOLE log4j.appender.R=com.hm.sage.bigdata.spark.log.RoolingAndDateFileAppender log4j.appender.R.Encoding=UTF-8 log4j.appender.R.file=/Users/shengwen/tmp/logs/logRecoed.log log4j.appender.R.Append=true log4j.appender.R.DatePattern=yyyy-MM-dd log4j.appender.R.MaxFileSize=5MB log4j.appender.R.maxIndex=10 log4j.appender.R.expirDays=4 log4j.appender.R.isCleanLog=true log4j.appender.R.layout.ConversionPattern=[%-5p] [%d{yyyy-MM-dd HH:mm:ss}] [%C{1}:%M:%L] %m%n log4j.appender.R.layout=org.apache.log4j.PatternLayout #console log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout.ConversionPattern=[%-5p] [%d{yyyy-MM-dd HH:mm:ss}] [%C{1}:%M:%L] %m%n log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
測試程式碼段
package com.hm.sage.bigdata.spark.log; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class TextLog { public static void main(String[] args) { Log log = LogFactory.getLog(TextLog.class); for(int i=0;i<=500000;i++){ System.out.println("迴圈"+"--"+i); try{ System.out.println(1%0); }catch(Exception e){ log.info("異常資訊"+i+":"+e); } } } }