感谢:http://byx5185.iteye.com/blog/1616034
1、重写FileAppender :
package com.bankht.cis.tps.apps.tps.util; import org.apache.log4j.FileAppender; import org.apache.log4j.Layout; import org.apache.log4j.helpers.OptionConverter; import org.apache.log4j.spi.LoggingEvent; import java.io.*; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.TreeMap; /** * 名称: TraceLogFileAppender.java<br> * 描述: 该appender是仿照log4j中RollingFileAppender写的 * 可配置备份天数,包含当天 * filesize为字节数<br> * 批次:name<br> * 创建时间: 2018年7月23日<br> * 修改时间:<br> * 编写人员:xxx <br> * 版本号:1.0 */ public class CustomTraceLogFileAppender extends FileAppender { protected long maxFileSize = 10485760L;//file.length,字节数 protected int maxDaysIndex = 1;//备份天数,包含当天 private long nextRollover = 0; private static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); private static String separator = "."; public CustomTraceLogFileAppender() {} public CustomTraceLogFileAppender(Layout layout, String filename, boolean append) throws IOException { super(layout, filename, append); } public CustomTraceLogFileAppender(Layout layout, String filename) throws IOException { super(layout, filename); } public int getMaxDaysIndex(){return maxDaysIndex;} public long getMaximumFileSize() { return maxFileSize; } public void setMaxDaysIndex(int maxDays) { maxDaysIndex = maxDays; } public void setMaximumFileSize(long maxFileSize) { this.maxFileSize = maxFileSize; } public void setMaxFileSize(String value) { maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1L); } protected void setQWForFiles(Writer writer) { qw = new CustomCountingQuietWriter(writer, errorHandler,this.encoding); } //启动时专用 public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize) throws IOException { String temp = getStartupFileName(fileName); super.setFile(temp, append, this.bufferedIO, this.bufferSize); if (append) { File f = new File(temp); ((CustomCountingQuietWriter)qw).setCount(f.length()); } //每次启动时,检验是否超出备份数量,超出则删除最旧日期 countFile(temp,maxDaysIndex); } private String getStartupFileName(String name) { String filePath = name.substring(0,name.lastIndexOf("/")+1); String[] strs = name.split("\."); File[] files = new File(filePath).listFiles(new CustomLogStartupFileFilter(strs[1])); //treemap默认是升序,取最后一个即为最新文件. TreeMap<Long, String> treeMap = new TreeMap<Long, String>(); if(files==null || files.length == 0){ if(strs.length==3){ StringBuffer sb = new StringBuffer(); String now = sdf.format(new Date()); return sb.append(strs[0]).append(separator) .append(strs[1]).append(separator) .append(now).append(separator) .append("1").append(separator).append("log").toString(); } return name; }else{ for(File temp : files){ treeMap.put(temp.lastModified(),temp.getPath()); } name = treeMap.lastEntry().getValue(); String now = sdf.format(new Date()); String[] strs1 = name.split("\."); if(strs1.length == 5){//符合日志文件名格式 StringBuffer sb = new StringBuffer(); if(now.equals(strs1[2])){ return sb.append(strs[0]).append(separator) .append(strs1[1]).append(separator) .append(strs1[2]).append(separator) .append(strs1[3]).append(separator).append("log").toString(); }else{ return sb.append(strs[0]).append(separator) .append(strs1[1]).append(separator) .append(now).append(separator) .append("1").append(separator).append("log").toString(); } } } return name; } public synchronized void setCustomFile(String fileName, boolean append, boolean bufferedIO, int bufferSize) throws IOException { super.setFile(fileName, append, this.bufferedIO, this.bufferSize); if (append) { File f = new File(fileName); ((CustomCountingQuietWriter)qw).setCount(f.length()); } } protected void subAppend(LoggingEvent event) { String nowDate = sdf.format(new Date()); String[] strs = fileName.split("\."); String fileDate = strs[2]; if(!nowDate.equals(fileDate)){ try { //新建文件,当切换日期时,文件名中的序号都是从1开始 String newFileName = getFileName(fileName,1); this.setCustomFile(newFileName, true, bufferedIO, bufferSize); //计算备份天数,多出删掉 countFile(newFileName,maxDaysIndex); } catch (IOException e) { if (e instanceof InterruptedIOException) { Thread.currentThread().interrupt(); } } } super.subAppend(event);//先写入数据 if ((fileName != null) && (qw != null)) { long size = ((CustomCountingQuietWriter)qw).getCount(); if ((size >= maxFileSize) && (size >= nextRollover)) { this.closeFile(); fileName = getFileName(fileName,1); try { this.setCustomFile(fileName, true, bufferedIO, bufferSize); nextRollover = 0; } catch (IOException e) { if (e instanceof InterruptedIOException) { Thread.currentThread().interrupt(); } } } } } /** * 系统名称.实例名称.日期.文件编号.log * @param name * @param i * @return */ private static String getFileName(String name,int i) { String date = sdf.format(new Date()); String filePath = name.substring(0, name.lastIndexOf("/")+1); String currentName = name.substring(name.lastIndexOf("/")+1); String[] str = currentName.split("\."); if(str.length>=3){//启动时,文件名:系统名.实例名.log,长度为3 String fileName = ""; fileName = str[0]+separator+str[1]+separator+date+separator; int nums = 0; if(str.length==5){ String num = str[3]; String fileDate = str[2]; if(!"".equals(num) && num != null && date.equals(fileDate)){ nums = Integer.parseInt(num); } } nums= nums + i; fileName = filePath + fileName + nums + ".log"; name = fileName; } return name; } /** * 获取几天前的日期,格式yyyyMMdd * @param days 天数 * @return */ public static String getBeforeDate(int days){ Calendar cal = Calendar.getInstance(); cal.add(cal.DATE, -days); Date resultDate = cal.getTime(); return sdf.format(resultDate); } /** * * @param fileName 文件名称(包括路径) * @param MaxDaysIndex 计算日志文件个数,当达到最大保留数时,将最早生成的日志文件删除 */ public static void countFile(String fileName,int MaxDaysIndex){ String delDate = getBeforeDate(MaxDaysIndex); String filePath = fileName.substring(0, fileName.lastIndexOf("/")); File file = new File(filePath); if(file.isDirectory()){ File[] files = file.listFiles(new CustomLogFileFilter(delDate)); if(files != null && files.length>0){ for(File temp:files){ temp.delete(); } } } } } /** * 文件过滤器 * 删除文件时专用 */ class CustomLogFileFilter implements FileFilter { private String delDate; public CustomLogFileFilter(String delDate) { this.delDate = delDate; } /** * * @param file 路径+文件名 * @return */ @Override public boolean accept(File file) { if (delDate == null || file.isDirectory()) { return false; } else { String[] strs = file.getName().split("\."); if(strs!=null && strs.length>=3){ if(strs[2].compareTo(delDate)<=0){//删除备份天数之前的文件 return true; } } return false; } } } class CustomLogStartupFileFilter implements FileFilter { private String serverName; public CustomLogStartupFileFilter(String serverName) { this.serverName = serverName; } /** * * @param file 路径+文件名 * @return */ @Override public boolean accept(File file) { //过滤文件夹中符合系统名称.实例名称.日期.文件编号.log格式的文件,实例名与当前实例名一致. if(file.getName().split("\.").length == 5 && serverName.equals(file.getName().split("\.")[1])){ return true; } return false; } }
2、
package com.bankht.cis.tps.apps.tps.util; import org.apache.log4j.helpers.QuietWriter; import org.apache.log4j.spi.ErrorHandler; import java.io.IOException; import java.io.Writer; /** * 重写CustomCountingQuietWriter * 计算长度时,设置字符级 * Created by xxx on 2018/7/24. */ public class CustomCountingQuietWriter extends QuietWriter { protected long count; protected String encoding; public CustomCountingQuietWriter(Writer writer, ErrorHandler eh, String encoding) { super(writer, eh); this.encoding = encoding; } public void write(String string) { try { this.out.write(string); this.count += (long)string.getBytes(this.encoding).length; } catch (IOException var3) { this.errorHandler.error("Write failure.", var3, 1); } } public long getCount() { return this.count; } public void setCount(long count) { this.count = count; } }
2、 log4j.properties文件中配置:
其中CustomTraceLogFileAppender为重写的FileAppender。
MaxFileSize 文件大小
MaxDaysIndex 备份天数
# Set root logger level to DEBUG and its only appender to CONSOLE.
log4j.rootLogger=INFO,log
#CONSOLE
#log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
#log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
#log4j.appender.CONSOLE.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%t] %-5p %C{1} : %m%n
#route trace log
log4j.appender.log=org.apache.log4j.RollingFileAppender
log4j.appender.log.File=/route/route-trace-${log.name}.log
log4j.appender.log.MaxFileSize=200000KB
log4j.appender.log.MaxBackupIndex=200
log4j.appender.log.layout=org.apache.log4j.PatternLayout
log4j.appender.log.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS}[%t][%c][%p]-%m%n
#SQL
log4j.logger.java.sql.Connection=INFO
log4j.logger.java.sql.Statement=INFO
log4j.logger.java.sql.PreparedStatement=INFO
log4j.logger.java.sql.ResultSet=INFO
#trace log
log4j.logger.traceLog=INFO,traceLog
log4j.additivity.traceLog=false
log4j.appender.traceLog=com.bankht.cis.tps.apps.tps.util.CustomTraceLogFileAppender
log4j.appender.traceLog.Append=true
log4j.appender.traceLog.MaxFileSize=20480KB
log4j.appender.traceLog.MaxDaysIndex=7
log4j.appender.traceLog.encoding=UTF-8
log4j.appender.traceLog.File=/route/tracelog/GCSC-D.${log.name}.log
log4j.appender.traceLog.layout=org.apache.log4j.PatternLayout
log4j.appender.traceLog.layout.ConversionPattern=%m%n