自定义log4j生成的log文件名
来源:互联网 发布:php基础教程 第5版 pdf 编辑:程序博客网 时间:2024/06/05 00:16
很多时候,log4j的RollingFileAppender配置如下:
log4j.logger.cn.lettoo.Test=INFO, filelog4j.appender.file=org.apache.log4j.RollingFileAppenderlog4j.appender.file.MaxFileSize=100KBlog4j.appender.file.MaxBackupIndex=10log4j.appender.file.File=test.loglog4j.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, filelog4j.appender.file=org.apache.log4j.RollingFileAppenderlog4j.appender.file.MaxFileSize=100KBlog4j.appender.file.MaxBackupIndex=10log4j.appender.file.File=test-%s_%s_0.%s.loglog4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=[%d{MM/dd/yyyy HH:mm:ss.SSS} %m%n
虽然以上的做法满足了我的要求,但是我感觉也有缺点,主要是:
- 配置文件必须要按我自定义的格式来写,即log4j.appender.file.File=test-%s_%s_0.%s.log不能搞错了
- RollingFileAppender的几个方法扩展的都不好,还把原来的代码copy过来修改的。
转载地址:http://lettoo.iteye.com/blog/1226671
0 0
- 自定义log4j生成的log文件名
- Log4j 生成动态年月日log文件名
- log4j - 指定log文件名 动态生成Log文件
- log4j生成有日期的日志文件名
- log4j生成有日期的日志文件名
- log4j生成有日期的日志文件名
- log4j生成log文件路径的设置
- log4j不生成log文件
- 如何使log4j生成json格式的log
- log4j根据变量动态生成文件名
- java log4j log日志文件名(+日期标记)
- log4j在jetty服务器下生成的log日志文件的相对路径问题
- 备忘-按日期、时间或大小生成log文件的log4j配置方案
- 按日期、时间或大小生成log文件的log4j配置方案
- 备忘-按日期、时间或大小生成log文件的log4j配置方案
- 日期、时间或大小生成log文件的log4j配置方案
- swing导出的jar文件读取log4j.properties及根据相对路径生成log
- 09 转 备忘-按日期、时间或大小生成log文件的log4j配置方案
- Asynctask解析
- 虚拟化技术漫谈
- 通过signapk.jar 为Android 应用程序签名,并优化签名后的APK应用程序
- Command Injection
- Java EE项目中的异常处理
- 自定义log4j生成的log文件名
- C++错误:“__w64 unsigned int”的前面应有“;”
- keil warning: #1-D: last line of file ends without
- iptables--静态防火墙实例教程
- 青春的迷茫
- UVa 11417 GCD (欧拉φ函数)
- 强制转换(1)dynamic_cast
- Ubuntu操作系统学习笔记之vsftpd的安装
- 非递归前中后序遍历(多种方式)