浏览 3842 次
锁定老帖子 主题:自定义log4j生成的log文件名
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-11-01
最后修改:2011-11-01
log4j.logger.cn.lettoo.Test=INFO, file log4j.appender.file=org.apache.log4j.RollingFileAppender log4j.appender.file.MaxFileSize=100KB log4j.appender.file.MaxBackupIndex=10 log4j.appender.file.File=test.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=[%d{MM/dd/yyyy HH:mm:ss.SSS} %m%n RollingFileAppender会自动在一个文件满了之后,生成一个如text.log.1的文件,一直生成到text.log.x(x值可配置log4j.appender.file.MaxBackupIndex=10)为止,再回写text.log。 当我们有需要在产生一些自定义的log文件名的时候,比如: 引用 test_[process_name]_0_20111031.log test_[process_name]_1_20111031.log test_[process_name]_2_20111031.log ...... 要在文件名显示是哪一个进程名,第一个文件为0,后面是1,2,3......,并且要加上日期,再使用RollingFileAppender做简单的配置是无论如何也实现不了了。 打开RollingFileAppender.java的源码,我看到它主要是用setFile(),subAppend()和rollOver()这几个方法来实现具体的功能的: public // synchronization not necessary since doAppend is alreasy synched void rollOver() { File target; File file; if (qw != null) { long size = ((CountingQuietWriter) qw).getCount(); LogLog.debug("rolling over count=" + size); // if operation fails, do not roll again until // maxFileSize more bytes are written nextRollover = size + maxFileSize; } LogLog.debug("maxBackupIndex="+maxBackupIndex); boolean renameSucceeded = true; // If maxBackups <= 0, then there is no file renaming to be done. if(maxBackupIndex > 0) { // Delete the oldest file, to keep Windows happy. file = new File(fileName + '.' + maxBackupIndex); if (file.exists()) renameSucceeded = file.delete(); // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2} for (int i = maxBackupIndex - 1; i >= 1 && renameSucceeded; i--) { file = new File(fileName + "." + i); if (file.exists()) { target = new File(fileName + '.' + (i + 1)); LogLog.debug("Renaming file " + file + " to " + target); renameSucceeded = file.renameTo(target); } } if(renameSucceeded) { // Rename fileName to fileName.1 target = new File(fileName + "." + 1); this.closeFile(); // keep windows happy. file = new File(fileName); LogLog.debug("Renaming file " + file + " to " + target); renameSucceeded = file.renameTo(target); // // if file rename failed, reopen file with append = true // if (!renameSucceeded) { try { this.setFile(fileName, true, bufferedIO, bufferSize); } catch(IOException e) { if (e instanceof InterruptedIOException) { Thread.currentThread().interrupt(); } LogLog.error("setFile("+fileName+", true) call failed.", e); } } } } // // if all renames were successful, then // if (renameSucceeded) { try { // This will also close the file. This is OK since multiple // close operations are safe. this.setFile(fileName, false, bufferedIO, bufferSize); nextRollover = 0; } catch(IOException e) { if (e instanceof InterruptedIOException) { Thread.currentThread().interrupt(); } LogLog.error("setFile("+fileName+", false) call failed.", e); } } } public synchronized void setFile(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); ((CountingQuietWriter) qw).setCount(f.length()); } } /** This method differentiates RollingFileAppender from its super class. @since 0.9.0 */ protected void subAppend(LoggingEvent event) { super.subAppend(event); if(fileName != null && qw != null) { long size = ((CountingQuietWriter) qw).getCount(); if (size >= maxFileSize && size >= nextRollover) { rollOver(); } } } 如果我继承这个类,然后在子类里实现它的这三个方法,不就可以实现我要的功能了吗? 代码如下: public class MWLogFileAppender extends RollingFileAppender { private long nextRollover = 0; public void rollOver() { File target; File file; if (qw != null) { long size = ((CountingQuietWriter) qw).getCount(); LogLog.debug("rolling over count=" + size); // if operation fails, do not roll again until // maxFileSize more bytes are written nextRollover = size + maxFileSize; } LogLog.debug("maxBackupIndex=" + maxBackupIndex); boolean renameSucceeded = true; // If maxBackups <= 0, then there is no file renaming to be done. if (maxBackupIndex > 0) { // Delete the oldest file, to keep Windows happy. //file = new File(fileName + '.' + maxBackupIndex); file = new File(getRollingFileName(fileName, maxBackupIndex)); if (file.exists()) renameSucceeded = file.delete(); // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, // 2} for (int i = maxBackupIndex - 1; i >= 1 && renameSucceeded; i--) { //file = new File(fileName + "." + i); file = new File(getRollingFileName(fileName, i)); if (file.exists()) { //target = new File(fileName + '.' + (i + 1)); target = new File(getRollingFileName(fileName, i+1)); LogLog.debug("Renaming file " + file + " to " + target); renameSucceeded = file.renameTo(target); } } if (renameSucceeded) { // Rename fileName to fileName.1 //target = new File(fileName + "." + 1); target = new File(this.getRollingFileName(fileName, 1)); this.closeFile(); // keep windows happy. file = new File(fileName); LogLog.debug("Renaming file " + file + " to " + target); renameSucceeded = file.renameTo(target); // // if file rename failed, reopen file with append = true // if (!renameSucceeded) { try { this.setFile(fileName, true, bufferedIO, bufferSize); } catch (IOException e) { if (e instanceof InterruptedIOException) { Thread.currentThread().interrupt(); } LogLog.error("setFile(" + fileName + ", true) call failed.", e); } } } } // // if all renames were successful, then // if (renameSucceeded) { try { // This will also close the file. This is OK since multiple // close operations are safe. this.setFile(fileName, false, bufferedIO, bufferSize); nextRollover = 0; } catch (IOException e) { if (e instanceof InterruptedIOException) { Thread.currentThread().interrupt(); } LogLog.error("setFile(" + fileName + ", false) call failed.", e); } } } private String getRollingFileName(String fileName, int index) { Pattern p = Pattern.compile("_\\d+\\."); Matcher m=p.matcher(fileName); return m.replaceFirst(String.format("_%d.", index)); } public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize) throws IOException { String processName = "01"; SimpleDateFormat format = new SimpleDateFormat("MMddyyyy"); String dateString = format.format(new Date(System.currentTimeMillis())); String processId = String.valueOf(Thread.currentThread().getId()); String temp = String.format(fileName, processName, dateString, processId); //System.out.println(temp); super.setFile(temp, append, bufferedIO, bufferSize); } protected void subAppend(LoggingEvent event) { super.subAppend(event); if (fileName != null && qw != null) { long size = ((CountingQuietWriter) qw).getCount(); if (size >= maxFileSize && size >= nextRollover) { rollOver(); } } } } 在setFile方法里,通过String的替换来实现我要的自定义字符串的功能,当然,这里只是一个示例。 文件满了之后生成新的文件编号,不再在log后面加数据,而是在文件名体现,我这里加了一个getRollingFileName()来根据正则表达式来替换。 当然,配置文件可以修改如下了: log4j.logger.cn.lettoo.Test=INFO, file log4j.appender.file=org.apache.log4j.RollingFileAppender log4j.appender.file.MaxFileSize=100KB log4j.appender.file.MaxBackupIndex=10 log4j.appender.file.File=test-%s_%s_0.%s.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=[%d{MM/dd/yyyy HH:mm:ss.SSS} %m%n 虽然以上的做法满足了我的要求,但是我感觉也有缺点,主要是:
目前也没有想到更好的方法,暂时先记下来。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |