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

目录
  • 自定义log4j日志文件命名规则
    • 根据log4j的API定义自己的FileAppender
    • 对应的log4j.properties的配置文件如下
    • 输出的日志文件命名如下
  • log4j自定义生成文件的名称
    • log4j.properties
    • MyRollingFileAppender.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.

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

(0)

相关推荐

  • Log4j定时打印日志及添加模块名配置的Java代码实例

    配置间隔时间,定时打印日志  接到个需求,通过log4j定时打印日志,需求描述如下:需要能够定时打印日志,时间间隔可配.说到定时,首先想到了DailyRollingFileAppender类,各种定时,根据datePattern,这个可以参考类SimpleDateFormat类,常见的一些定时设置如下: '.'yyyy-MM: 每月 '.'yyyy-ww: 每周 '.'yyyy-MM-dd: 每天 '.'yyyy-MM-dd-a: 每天两次 '.'yyyy-MM-dd-HH: 每小时 '.'yy

  • 使用log4j输出一个类的所有参数的值

    目录 log4j输出一个类的所有参数的值 log4j各参数打印输出内容 log4j输出一个类的所有参数的值 项目用到的是日志框架是slf4j+log4j,在使用的过程中,如果要输出一个元素的值,一般都是这样写 logger.info("当前登录人的姓名是:{}", userinfo.getName()); 这样就会输出:当前登录人的姓名是:张三 但是如果我想要输出一个类userinfo中所有的参数信息,比如说,姓名,年龄,电话等信息,如果这样就会出问题 logger.info(&quo

  • org.slf4j.Logger中info()方法的使用详解

    目录 org.slf4j.Logger中info()方法 如果info()方法参数为以下类型 使用范例1 使用范例2 如果info()方法参数如下 使用范例1 如果info()方法参数如下 使用范例1 log.info()传入多个参数的方法 org.slf4j.Logger中info()方法 如果info()方法参数为以下类型 public void info(String format, Object argArray[]) { if(logger.isInfoEnabled()) { For

  • java自定义日志输出文件(log4j日志文件输出多个自定义日志文件)

    log4j输出多个自定义日志文件 如果在实际应用中需要输出独立的日志文件,怎样才能把所需的内容从原有日志中分离,形成单独的日志文件呢? 先看一个常见的log4j.properties文件,它是在控制台和test.log文件中记录日志: 复制代码 代码如下: log4j.rootLogger=DEBUG, stdout, logfile log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layo

  • 浅谈log4j的rootLogger及其他坑爹的地方

    目录 log4j的rootLogger及其他坑爹地方 经过试验发现!!!! 对于申明appender的包rootLogger的级别设置不起作用 log4j rootLogger配置 log4j.rootLogger=INFO,db语法为 log4j的rootLogger及其他坑爹地方 这里用的是org.apache.log4j.Logger log4j.rootLogger=error, stdout log4j.appender.appenderName=org.apache.log4j.As

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

    目录 自定义log4j日志文件命名规则 根据log4j的API定义自己的FileAppender 对应的log4j.properties的配置文件如下 输出的日志文件命名如下 log4j自定义生成文件的名称 log4j.properties MyRollingFileAppender.java 自定义log4j日志文件命名规则 项目中的日志需要采用一致的命名规范和文件规范,命名规则为:项目模块标识_index_日期时间_日志级别.log,且每个级别日志文件放在单独的文件夹,且每个文件夹下日志的数

  • Log4j 日志文件Linux/Mac/Windows通用存放位置设置方法

    log4j1/log4j2中category的配置以及log的输出位置(windows和linux通用的log输出位置) 一.场景和需求 假设我现在有3个独立的用project(暂时用maven关联起来,当然也可以不用maven),一个是提供公共服务的infrastructure,一个是提供存储的persister,一个是提供搜索的searcher,其中提供基础服务的所有的类,例如DateUtils,HttpUtils等工具类都位于目录com.chuanliu.platform.activity

  • spring boot自定义log4j2日志文件的实例讲解

    背景:因为从 spring boot 1.4开始的版本就要用log4j2 了,支持的格式有json和xml两种格式,此次实践主要使用的是xml的格式定义日志说明. spring boot 1.5.8.RELEASE 引入log4j2的开发步骤如下: 1.首先把spring-boot-starter-web以及spring-boot-starter包下面的spring-boot-starter-logging排除,然后引入spring-boot-starter-log4j2包. <dependen

  • Java 配置log4j日志文件路径 (附-获取当前类路径的多种操作)

    1 日志路径带来的痛点 Java 项目中少不了要和log4j等日志框架打交道, 开发环境和生产环境下日志文件的输出路径总是不一致, 设置为绝对路径的方式缺少了灵活性, 每次变更项目路径都要修改文件, 目前想到的最佳实现方式是: 根据项目位置自动加载并配置文件路径. 本文借鉴 Tomcat 的配置方式 "${catalina.home}/logs/catalina.out", 通过相对路径的方式设置日志的输出路径, 有其他解决方案的小伙伴, 请直接评论区交流哦

  • 详解Log4j 日志文件存放位置设置

    以DailyRollingFileAppender 为例:假设每天一个日志文件 有以下设置: log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender log4j.appender.A1.File=app.log log4j.appender.A1.DatePattern='.'yyyy-MM-dd log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.append

  • Pytest之测试命名规则的使用

    背景: pytest以特定规则搜索测试用例,所以测试用例文件.测试类以及类中的方法.测试函数这些命名都必须符合规则,才能被pytest搜索到并加入测试运行队列中. 默认搜索规则: 如果pytest命令行有指定目录,则从该目录中开始查找测试用例文件,如果没有指定,则从当前运行目录开始查找文件.注意,该查找是递归查找,子目录中的文件也会被查找到. 并不是能够查找到目录下的所有文件,只有符合命名规则的文件才会被查找.默认规则是以test_开头或者以_test结尾的.py文件. 在测试文件中查找Test

  • 关于log4j日志扩展---自定义PatternLayout

    目录 log4j日志扩展---PatternLayout 这是log4j官网上的配置 下载官方文件发现有这样两个类 给大家举个例子 故完整的代码 扩展log4j---自定义日志文件创建 log4j配置如下 log4j日志扩展---PatternLayout 目前扩展log4j的日志一般使用扩展adaper的方法,这里使用一种扩展PatternLayout方法. log4j.rootLogger=debug, stdout, R log4j.appender.stdout=org.apache.l

  • log4j日志格式加入自定义字段信息方式

    目录 log4j日志格式加入自定义字段信息 log4j2入库自定义字段类型 官方API文档中只提供了几个属性 设置isNumber="true" log4j日志格式加入自定义字段信息 在使用log4j日志的时候,有时需要在日志中加入自定义字段信息,例如在日志中加入登录用户的信息等,这时就可以使用org.apache.log4j.MDC来实现该功能: 1.在Action的方法中,直接使用 MDC.put("username",getUserInfo().getName

  • springboot+log4j.yml配置日志文件的方法

    一,Maven 依赖 pom.xml配置 1, 去掉默认日志,以便切换到log4j2的日志依赖 2, 然后添加如下两个日志依赖 二,在工程根目录下添加 lo4g2.yml 配置文件 2, 配置文件内容 <!-- 配置 log4j2 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artif

随机推荐