自定义log4j日志文件命名规则说明

网友投稿 1519 2022-11-12

自定义log4j日志文件命名规则说明

自定义log4j日志文件命名规则说明

目录自定义log4j日志文件命名规则根据log4j的API定义自己的FileAppender对应的log4j.properties的配置文件如下输出的日志文件命名如下log4j自定义生成文件的名称log4j.propertiesMyRollingFileAppender.java

自定义log4j日志文件命名规则

项目中的日志需要采用一致的命名规范和文件规范,命名规则为:项目模块标识_index_日期时间_日志级别.log,且每个级别日志文件放在单独的文件夹,且每个文件夹下日志的数量不得超过10个,当数量超过限制时,删除相对较旧的日志,保留较新的日志。

但是发现log4j并不能满足此要求,于是

根据log4j的API定义自己的FileAppender

代码如下:

package com.dear.simpler.dbrpc.util.log;

import java.io.File;

import java.io.IOException;

import java.io.InterruptedIOException;

import java.text.SimpleDateFormat;

import java.util.Arrays;

import java.util.Comparator;

import java.util.Date;

import java.util.concurrent.atomic.AtomicInteger;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import org.apache.log4j.RollingFileAppender;

import org.apache.log4j.helpers.CountingQuietWriter;

import org.apache.log4j.helpers.LogLog;

import org.apache.log4j.spi.LoggingEvent;

/**;

*

* @author lixiang

* 自定义log文件的命名规则

*/

public class MyLogFileAppender extends RollingFileAppender {

private long nextRollover = 0;

private static AtomicInteger logIndex = new AtomicInteger(0); //index

public void rollOver() {

File file = null;

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);

if (maxBackupIndex > 0) {

file = new File(getRollingFileName(fileName, logIndex.incrementAndGet()));

if (fileExisted(file)){

file = new File(getRollingFileName(fileName, logIndex.incrementAndGet()));

}

deleteOldFile(file.getParentFile(), maxBackupIndex);

this.closeFile();

}

try {

this.setFile(getRollingFileName(fileName, logIndex.get()), 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) { //使用正则表达式替代index

Pattern p = Pattern.compile("_\\d+\\_");

Matcher m=p.matcher(fileName);

String str = m.replaceFirst(String.format("_%d_", index));

SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); //日期

String dateString = format.format(new Date(System.currentTimeMillis()));

str = str.replaceAll("\\d{14}", dateString);

return str;

}

public synchronized void setFile(String fileName, boolean append, //修改文件名

boolean bufferedIO, int bufferSize) throws IOException {

SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); //日期

String dateString = format.format(new Date(System.currentTimeMillis()));

String temp = String.format(fileName , dateString); //文件名

super.setFile(temp, append, bufferedIO, bufferSize);

if(append) {

File f = new File(temp);

((CountingQuietWriter)this.qw).setCount(f.length());

}

}

private boolean fileExisted(File file){

boolean res = false;

String[] fts = file.getName().split("_");

File parentFile = file.getParentFile();

for(File f : parentFile.listFiles()){

String[] fns = f.getName().split("_");

if(fns[0].equals(fts[0]) && fns[1].equals(fts[1])){

res = true;

break;

}

}

return res;

}

private void deleteOldFile(File dir , int maxInt){

if(getFileNum(dir) >= maxBackupIndex ){

File[] files = orderByDate(dir);

for (int i = 0; i <= files.length - maxBackupIndex; i++) {

File f = files[i];

f.delete();

}

}

}

private int getFileNum(File file){

return file.list().length;

}

//将文件按日期排序

public File[] orderByDate(File dir) {

File[] fs = dir.listFiles();

Arrays.sort(fs,new Comparator< File>(){

@Override

public int compare(File f1, File f2) {

long diff = f1.lastModified() - f2.lastModified();

if (diff > 0)

return 1;

else if (diff == 0)

return 0;

else

return -1;

}

@Override

public boolean equals(Object obj) {

return true;

}

});

return fs;

}

@Override

protected void subAppend(LoggingEvent event) {

super.subAppend(event);

if (fileName != null && qw != null) {

long size = ((CountingQuietWriter) qw).getCount();

if (size >= maxFileSize && size >= nextRollover) {

rollOver();

}

}

}

}

对应的log4j.properties的配置文件如下

### set log levels ###

log4j.rootLogger = out,E,I

#log4j.logger.com.dear.simpler.dbrpc.util.log.TestUtil=out,D

log4j.appender.D = com.dear.simpler.dbrpc.util.log.MyLogFileAppender

log4j.appender.D.File = ../../logs/db_logs/debug/DB_0_%s_debug.log

log4j.appender.D.Append = true

log4j.appender.D.MaxFileSize=1024MB

log4j.appender.D.MaxBackupIndex=10

log4j.appender.D.Threshold = DEBUG

log4j.appender.D.layout = com.dear.simpler.dbrpc.util.log.ExPatternLayout

log4j.appender.D.layout.ConversionPattern = [%d{yyyy/MM/dd HH:mm:ss,SSS}][%T:%t][%p][%F:%L:%M][%m]%n

log4j.appender.E = com.dear.simpler.dbrpc.util.log.MyLogFileAppender

log4j.appender.E.File = ../../logs/db_logs/error/DB_0_%s_error.log

log4j.appender.E.Append = true

log4j.appender.E.MaxFileSize=10MB

log4j.appender.E.MaxBackupIndex=10

log4j.appender.E.Threshold = ERROR

log4j.appender.E.layout = com.dear.simpler.dbrpc.util.log.ExPatternLayout

log4j.appender.E.layout.ConversionPattern = [%d{yyyy/MM/dd HH:mm:ss,SSS}][%T:%t][%p][%F:%L:%M][%m]%n

log4j.appender.I = com.dear.simpler.dbrpc.util.log.MyLogFileAppender

log4j.appender.I.File = ../../logs/db_logs/info/DB_0_%s_info.log

log4j.appender.I.Append = true

log4j.appender.I.MaxFileSize=10MB

log4j.appender.I.MaxBackupIndex=10

log4j.appender.I.Threshold = INFO

log4j.appender.I.layout = com.dear.simpler.dbrpc.util.log.ExPatternLayout

log4j.appender.I.layout.ConversionPattern = [%d{yyyy/MM/dd HH:mm:ss,SSS}][%T:%t][%p][%F:%L:%M][%m]%n

输出的日志文件命名如下

log4j自定义生成文件的名称

我们在使用Log4j的RollingFileAppender循环生成文件的时候,生成的文件的名称有点儿恶心,例如,文件名称为app.log,那么生成的文件名依次为app.log.1,app.log.2,....

那么如何去改变生成文件的名称的规则呢?下面是一个简单示例:

log4j.properties

log4j.logger.major= INFO, majorMsg

log4j.additivity.logError = false

log4j.appender.majorMsg=com.zws.log.MyRollingFileAppender

log4j.appender.majorMsg.File=${catalina.home}/logs/itc/majorMsg.log

log4j.appender.majorMsg.layout=org.apache.log4j.PatternLayout

log4j.appender.majorMsg.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss}|%p|%C|%M|%L|%m%n

log4j.appender.majorMsg.MaxFileSize=1KB

log4j.appender.majorMsg.MaxBackupIndex=10

MyRollingFileAppender.java

package com.zws.log;

import java.io.File;

import java.io.IOException;

import java.io.InterruptedIOException;

import org.apache.log4j.Priority;

import org.apache.log4j.RollingFileAppender;

import org.apache.log4j.helpers.CountingQuietWriter;

import org.apache.log4j.helpers.LogLog;

import org.apache.log4j.spi.LoggingEvent;

/**

*

* @author wensh.zhu

*

*/

public class MyRollingFileAppender extends RollingFileAppender {

private long nextRollover = 0;

public void rollOver() {

File target;

File file;

if (qw != null) {

long size = ((CountingQuietWriter) qw).getCount();

nextRollover = size + maxFileSize;

}

LogLog.debug("maxBackupIndex=" + maxBackupIndex);

boolean renameSucceeded = true;

if (maxBackupIndex > 0) {

//删除序号最大(最早的文件)的文件

file = new File(genFileName(fileName, maxBackupIndex));

if (file.exists())

renameSucceeded = file.delete();

//所有文件名序号加1

for (int i = maxBackupIndex - 1; i >= 1 && renameSucceeded; i--) {

file = new File(genFileName(fileName, i));

if (file.exists()) {

target = new File(genFileName(fileName, i + 1));

renameSucceeded = file.renameTo(target);

}

}

if (renameSucceeded) {

target = new File(genFileName(fileName, 1));

this.closeFile();

file = new File(fileName);

renameSucceeded = file.renameTo(target);

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 (renameSucceeded) {

try {

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 genFileName(String name, int index) {

String fileName = "";

if (index > 0) {

String num = index < 10 ? "0" + index : String.valueOf(index);

fileName = name.replace(".log", "") + "_" + num + ".log";

} else {

fileName = name;

}

return fileName;

}

protected void subAppend(LoggingEvent event) {

super.subAppend(event);

if (fileName != null && qw != null) {

long size = ((CountingQuietWriter) qw).getCount();

if (size >= maxFileSize && size >= nextRollover) {

rollOver();

}

}

}

}

以上示例将文件名的生成规则为:如果文件名为app.log,那么后续的文件为app_01.log,app_02.log.

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:盈透证券 简单API 实战
下一篇:Qt 简单爬虫开发
相关文章

 发表评论

暂时没有评论,来抢沙发吧~