文档章节

Log4j的扩展-支持设置最大日志数量的DailyRollingFileAppender

Zero零_度
 Zero零_度
发布于 2017/07/24 19:55
字数 1309
阅读 12
收藏 0

Log4j现在已经被大家熟知了,所有细节都可以在网上查到,Log4j支持Appender,其中DailyRollingFileAppender是被经常用到的Appender之一。在讨论今天的主题之前,我们先看下另外一个Appender。

最常用的Appender——RollingFileAppender

下面是RollingFileAppender的一个Log4j配置样例(配置1):

按 Ctrl+C 复制代码

 

按 Ctrl+C 复制代码

RollingFileAppender使用MaxFileSize设置一个日志文件的最大大小,当产生多个日志时,会在日志名称后面加上".1"、".2"、……这样的后缀,我们可以看到RollingFileAppender有个属性MaxBackupIndex,这个属性通过限制日志文件名后缀".n"中的n大小来限制日志数量,比如上面MaxBackupIndex=10,其实最大日志数量为11。我们知道这个有这个限制是很必要的,当我们的程序在服务器上运行时,随着时间的迁移,日志会越来越多,如果对日志数量没有限制,日志大小会越来越大,最后甚至占满整个硬盘。

可以按照周期时间来滚动日志文件的Appender——DailyRollingFileAppender

下面是DailyRollingFileAppender的一个Log4j配置样例(配置2):

按 Ctrl+C 复制代码

 

按 Ctrl+C 复制代码

 

DailyRollingFileAppender特点是固定周期时间生成一个日志文件,比如,默认情况是每天生成一个文件。这种日志可以方便根据时间来定位日志位置,使日志清晰易查。但是这种日志有个不好地方是,不能限制日志数量,MaxBackupIndex属性和MaxFileSize在DailyRollingFileAppender中是无效的,我们上面已经提到限制日志数量的必要性。这里有两个解决办法:

  • linux上crontab+shell
  • java进程里面起一个线程,定期扫描日志文件夹。

但是这两种方法都不是很方便,有没有更好的办法呢?

重写DailyRollingFileAppender——MyDailyRollingFileAppender

查看DailyRollingFileAppender源代码,发现rollOver()方法是用来生成文件的,当调用subAppend()方法时会根据判断当前时间是否大于应该生成新文件的时间了(具体实现可以查看源码,逻辑还是比较清晰的),如果大于,就生成。首先把当前日志重命名,命名格式为test.log.yyyy-MM-dd-HH-mm,然后重新建test.log文件。看到这里我们就可以想,在rollOver()方法里面加上删除过多的日志就不行了吗,的确可以这么做:

复制代码

1 public class MyDailyRollingFileAppender extends DailyRollingFileAppender {
  2     private static Logger logger = LoggerFactory.getLogger(MyDailyRollingFileAppender.class);
  3     private int maxFileSize = 60;
  4 
  5 
  6     void rollOver() throws IOException {
  7         super.rollOver();
  8 
  9         logger.debug("保留文件数量" + maxFileSize + ",日志文件名称为:" + fileName);
 10         List<File> fileList = getAllLogs();
 11         sortFiles(fileList);
 12         logger.debug(fileList.toString());
 13         deleteOvermuch(fileList);
 14     }
 15 
 16     /**
 17      * 删除过多的文件
 18      * @param fileList 所有日志文件
 19      */
 20     private void deleteOvermuch(List<File> fileList) {
 21         if (fileList.size() > maxFileSize) {
 22             for (int i = 0;i < fileList.size() - maxFileSize;i++) {
 23                 fileList.get(i).delete();
 24                 logger.debug("删除日志" + fileList.get(i));
 25             }
 26         }
 27     }
 28 
 29     /**
 30      * 根据文件名称上的特定格式的时间排序日志文件
 31      * @param fileList
 32      */
 33     private void sortFiles(List<File> fileList) {
 34         Collections.sort(fileList, new Comparator<File>() {
 35             public int compare(File o1, File o2) {
 36                 try {
 37                     if (getDateStr(o1).isEmpty()) {
 38                         return 1;
 39                     }
 40                     Date date1 = sdf.parse(getDateStr(o1));
 41 
 42                     if (getDateStr(o2).isEmpty()) {
 43                         return -1;
 44                     }
 45                     Date date2 = sdf.parse(getDateStr(o2));
 46 
 47                     if (date1.getTime() > date2.getTime()) {
 48                         return 1;
 49                     } else if (date1.getTime() < date2.getTime()) {
 50                         return -1;
 51                     }
 52                 } catch (ParseException e) {
 53                     logger.error("", e);
 54                 }
 55                 return 0;
 56             }
 57         });
 58     }
 59 
 60     private String getDateStr(File file) {
 61         if (file == null) {
 62             return "null";
 63         }
 64         return file.getName().replaceAll(new File(fileName).getName(), "");
 65     }
 66 
 67     /**
 68      *  获取所有日志文件,只有文件名符合DatePattern格式的才为日志文件
 69      * @return
 70      */
 71     private List<File> getAllLogs() {
 72         final File file = new File(fileName);
 73         File logPath = file.getParentFile();
 74         if (logPath == null) {
 75             logPath = new File(".");
 76         }
 77 
 78         File files[] = logPath.listFiles(new FileFilter() {
 79             public boolean accept(File pathname) {
 80                 try {
 81                     if (getDateStr(pathname).isEmpty()) {
 82                         return true;
 83                     }
 84                     sdf.parse(getDateStr(pathname));
 85                     return true;
 86                 } catch (ParseException e) {
 87                     logger.error("", e);
 88                     return false;
 89                 }
 90             }
 91         });
 92         return Arrays.asList(files);
 93     }
 94     public int getMaxFileSize() {
 95         return maxFileSize;
 96     }
 97 
 98     public void setMaxFileSize(int maxFileSize) {
 99         this.maxFileSize = maxFileSize;
100     }
101 }

复制代码

 

首先,要注意的就是怎么判断日志文件夹中的日志是否是日志还是另外不相关的文件,比如备份的日志、控制台日志等。我使用的方法就是判断sdf.parse(name.replaceAll(file.getName(), ""))是否报异常,如果不报异常就说明这个文件是日志,当然不排除有的文件命名恰好符合这个格式,但是这样的文件在日志文件夹下,我们认为它就是一个日志文件也是合理的。然后我们根据sdf.parse(name.replaceAll(file.getName(), ""))解析出来的Date为所有日志进行升序排序放到一个队列中,再保留这个队列最后maxFileSize个文件的情况下,删除多余的日志文件。

然后,我们注意到我们上面的逻辑中用了maxFileSize这个变量,这个变量在MyDailyRollingFileAppender中,这个变量是怎么赋值的呢?

复制代码

log4j.appender.logfile=org.apache.log4j.MyDailyRollingFileAppender
log4j.appender.logfile.File=test.log
log4j.appender.logfile.DatePattern='.'yyyy-MM-dd-HH-m
log4j.appender.logfile.MaxFileSize=5
log4j.appender.logfile.Append=false
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern= [%d{yyyy-MM-dd HH\:mm\:ss}]%-5p %c(line\:%L) %x-%m%n

复制代码

其实Log4j支持这种通用的配置方法,注意上面配置第四行,不用另外添加其他任何代码。

本文转载自:http://www.cnblogs.com/rembau/p/5201001.html

共有 人打赏支持
Zero零_度
粉丝 68
博文 1246
码字总数 252959
作品 0
程序员
spring boot(8)默认日志logback配置

1 日志简介 Spring Boot使用Commons Logging记录所有内部日志,但是它将底层日志实现打开,为Java.Util.Logging,Log4J2和Logback提供默认配置。 在每个案例中,loggers都预先配置,以使用控...

刘胜球
2017/10/31
0
0
log4j.properties配置与加载应用

log4j.properties总结: 一、介绍 Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务 器、NT的事件记录器、U...

Sobey
2015/01/08
0
0
Java Log4J 使用教程(java日志)

简介 2. 安装 3. log4j基本概念 3.1. Logger 3.2. Appender 3.2.1. 使用ConsoleAppender 3.2.2. 使用FileAppender 3.2.3. 使用WriterAppender 3.3. Layout 3.4. 基本示例 3.4.1. SimpleLayou......

lgxheartlikesea
2014/02/13
0
0
commons-logging和log4j

一、日志系统介绍 日志的重要性是随着系统的膨胀而显现的,在一个庞大的系统中查错没有各种日志信息是寸步难行的。所以在系统加入日志是必须的。 最原始的日志方式,就是在程序的适当地方添加...

hulubo
2011/12/25
0
0
logback与Log4J的区别

Logback和log4j是非常相似的,如果你对log4j很熟悉,那对logback很快就会得心应手。下面列了logback相对于log4j的一些优点: 更快的实现 Logback的内核重写了,在一些关键执行路径上性能提升...

凯文加内特
2015/05/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

oracle 安装 PL/SQL Developer连接64位Oracle免安装配置

PL/SQL Developer连接64位Oracle 在64位系统上安装64位的Oracle数据库,但是没有对应的64位PL/SQL Developer,此时就不能使用PL/SQL Developer来进行直接连接的,所以要想实现连接还得需要其...

PeakFang-BOK
2分钟前
0
0
裁员寒冬袭来,30岁还在CRUD的Java程序员,拿什么安身立命?

就在近日,智联招聘公布的数据更是侧面印证了很多公司“瘦身”的事实:“2018年第二季度,小微企业用人需求较第一季度平均下降26.6%”。 裁员大潮正滚滚向前,席卷各行各业! 你做好失业的准...

Java填坑之路
5分钟前
0
0
第一章:什么是SpringCloud

第一章:什么是SpringCloud 何为微服务 在了解 SpringCloud之前,我们先来大致了解下 微服务这个概念吧。 传统单体架构 单体架构在小微企业比较常见,典型代表就是一个应用、一个数据库、一个...

DemonsI
10分钟前
0
0
环境搭建之八-- node.js

1.node.js官网下载64位二进制压缩包 node-v8.12.0-linux-x64.tar.xz 2.解压文件 2.1 xz格式文件为 tar格式 xz -d node-v8.12.0-linux-x64.tar.xz 此时文件已经转变为 node-v8.12.0-linux-x64...

imbiao
14分钟前
0
0
JVM调优浅谈

1.数据类型 java虚拟机中,数据类型可以分为两类:基本类型和引用类型。 基本类型的变量保存原始值,即:它代表的值就是数值本身,而引用类型的变量保存引用值。 “引用值”代表了某个对象的...

xtof
18分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部