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

作者:dream_lixiang 时间:2021-11-21 16:55:51 

自定义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自定义生成文件的名称

我们在使用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.

仅为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家

来源:https://blog.csdn.net/dream_lixiang/article/details/55264203

标签:自定义,log4j,日志文件,命名
0
投稿

猜你喜欢

  • Java中synchronized锁的深入理解

    2023-08-18 01:36:55
  • Spring项目中使用Junit单元测试并配置数据源的操作

    2022-06-02 05:32:27
  • 关于统计数字问题的算法

    2023-11-03 00:33:32
  • Spring依赖注入与第三方Bean管理基础详解

    2022-09-08 20:45:55
  • ElasticSearch查询文档基本操作实例

    2023-11-24 14:20:02
  • MybatisPlus多表连接查询的问题及解决方案

    2023-11-25 22:09:06
  • SpringBoot基于数据库的定时任务统一管理的实现

    2023-12-10 12:57:47
  • Java反射机制的简单讲解

    2023-12-12 20:49:13
  • Android Studio 多层级 Module 对 aar 引用问题解决方法

    2023-08-06 19:41:27
  • Java中ResultSetMetaData 元数据的具体使用

    2021-06-25 12:38:13
  • Java Redis Redisson配置教程详解

    2022-10-13 06:32:39
  • Java ThreadLocal的使用详解

    2023-11-29 04:48:43
  • Java分布式服务框架Dubbo介绍

    2022-09-16 01:27:53
  • Java Swing实现让窗体居中显示的方法示例

    2023-11-06 02:59:07
  • IDEA 2022 中的Lombok 使用基础教程

    2023-04-09 21:57:09
  • 关于Java反编译字节码文件

    2021-10-07 01:41:32
  • MyBatis超详细讲解如何实现分页功能

    2023-08-22 23:06:51
  • Java实现定时任务的方法详解

    2022-12-30 04:14:00
  • java开发RocketMQ之NameServer路由管理源码分析

    2023-10-27 20:56:12
  • Java try-catch-finally异常处理机制详解

    2023-10-02 20:29:00
  • asp之家 软件编程 m.aspxhome.com