前言

  Log4J的配置文件设置日志输出到文件可以按大小分割和每日分割,但是没有按每日以大小分割的综合配置,所以需要自定义一个类实现日志每日按大小生成多个文件。

类代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package com.foreversfj.util;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.log4j.RollingFileAppender;
import org.apache.log4j.helpers.CountingQuietWriter;
import org.apache.log4j.helpers.LogLog;

/**
* 自定义日志类
* @author FOREVERSFJ
* @date 2022年3月17日
* @description 滚动日志名称为:fileName.dateStr.log-index</br>
* 当前输出为:fileName.log
*/
public class RoolingAndDateFileAppender extends RollingFileAppender {
private String datePattern;
private String dateStr = "";// 文件的日期
private String isCleanLog = "true";
private String maxIndex = "100";
private String logname;
private File rootDir;

/**
* 执行方法
*/
@Override
public void rollOver() {
this.setDateStr(new SimpleDateFormat(getDatePattern()).format(new Date(System.currentTimeMillis())));
// 去除后缀名
this.setLogname(fileName.substring(0, fileName.length() - 4));
File target = null;
File file = null;
if (qw != null) {
long size = ((CountingQuietWriter) this.qw).getCount();
System.out.println("当前文件大小:" + size);
}
// 如果maxIndex<=0则不需命名
if (getMaxIndex() != null && Integer.parseInt(getMaxIndex()) > 0) {
// 删除旧文件
file = new File(getLogname() + "." + getDateStr() + "[" + Integer.parseInt(getMaxIndex()) + "].log");
// 是否已经达到最大数量设置,如存在则进行删除并重排
if (file.exists()) {
// 如果当天日志达到最大设置数量,则删除当天第一个日志,其他日志为尾号减一
Boolean boo = reLogNum();
if (!boo) {
LogLog.debug("日志滚动重命名失败!");
}
}
}
// 获取当天日期文件个数,并确定是否需要清理超出文件
int count = cleanLog();
// 生成新文件名称 eg: dpsInfo.2022-03-17[1].log
target = new File(getLogname() + "." + getDateStr() + "[" + (count + 1) + "].log");
this.closeFile();
file = new File(fileName);
LogLog.debug("重命名文件[" + file + "]为[" + target + "]");
file.renameTo(target);
try {
setFile(this.fileName, false, this.bufferedIO, this.bufferSize);
} catch (IOException e) {
LogLog.error("方法setFile(" + this.fileName + ", false)调用失败", e);
}
}
public int cleanLog() {
int count = 0;// 记录当天文件个数
if (Boolean.parseBoolean(getIsCleanLog())) {
File f = new File(fileName);
this.closeFile();
this.setRootDir(f.getParentFile());
File[] listFiles = getRootDir().listFiles();
for (File file : listFiles) {
// 目录下只有文件才会进行计算
if (file.isFile()) {
// 输出文件是昨天的文件且没有达到分割下限,则进行重命名
if (file.getName().contains(getDateStr())) { // 当天有分割大小的文件
count = count + 1;// 是当天日志,则+1
} else {
// 是输出文件,则判断其修改时间
if (file.getName().equals(f.getName())) {
// 如果不是同一天的目标输出文件,则对原文件进行重命名
if (!DateUtils.compareDay(DateUtils.createDate(file.lastModified()), new Date())) {
File target = new File(getRootDir() + File.separator + this.getLogname() + "."
+ DateUtils.format8Date(DateUtils.createDate(file.lastModified())) + ".log");
file.renameTo(target);
}
} else {
// 不是当天的日志,则全部清理到昨天的文件夹中
if (Boolean.parseBoolean(getIsCleanLog())) {
// 只处理文件名带log的
if (file.getName().contains("log")) {
File target = new File(
getRootDir() + File.separator + DateUtils.addDays(getDateStr(), -1));
if (!target.exists()) {
target.mkdir();
}
// 移动文件
target = new File(target + File.separator + file.getName());
file.renameTo(target);
}
}
}
}
}
}
}
return count;
}
/**
* 如果当天日志达到最大设置数量,则每次删除尾号为1的日志,
* 其他日志编号依次减去1,重命名
* @return
*/
public Boolean reLogNum() {
boolean renameTo = false;
File startFile = new File(getLogname() + "." + getDateStr() + "[1].log");
if (startFile.exists() && startFile.delete()) {
for (int i = 2; i <= Integer.parseInt(getMaxIndex()); i++) {
File target = new File(getLogname() + "." + getDateStr() + "[" + (i - 1) + "].log");
this.closeFile();
File file = new File(getLogname() + "." + getDateStr() + "[" + i + "].log");
renameTo = file.renameTo(target);
}
}
return renameTo;
}
public void setDatePattern(String datePattern) {
if (null != datePattern && !"".equals(datePattern)) {
this.datePattern = datePattern;
} else {
this.datePattern = "yyyy-mm-dd";
}
}
public String getDatePattern() {
return this.datePattern;
}
public String getDateStr() {
return dateStr;
}
public void setDateStr(String dateStr) {
this.dateStr = dateStr;
}
public String getIsCleanLog() {
return isCleanLog;
}
public void setIsCleanLog(String isCleanLog) {
this.isCleanLog = isCleanLog;
}
public String getMaxIndex() {
return maxIndex;
}
public void setMaxIndex(String maxIndex) {
this.maxIndex = maxIndex;
}
public File getRootDir() {
return rootDir;
}
public void setRootDir(File rootDir) {
this.rootDir = rootDir;
}
public String getLogname() {
return logname;
}
public void setLogname(String logname) {
this.logname = logname;
}
}

工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.foreversfj.util;

import java.util.Calendar;
import java.util.Date;

public class DateUtils {

public static Date createDate(long millis) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(millis);
return calendar.getTime();
}
public static boolean compareDay(Date date1, Date date2) {
Calendar calendar1 = createCalendar(date1);
Calendar calendar2 = createCalendar(date2);
if (calendar1.get(Calendar.YEAR) != calendar2.get(Calendar.YEAR)) {
return false;
}
if (calendar1.get(Calendar.DAY_OF_YEAR) != calendar2.get(Calendar.DAY_OF_YEAR)) {
return false;
}
return true;
}
public static Calendar createCalendar(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return calendar;
}
}

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
log4j.rootCategory=DEBUG, CONSOLE, FILE
log4j.category.com.inca=INFO

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d-%-5r %-5p [%c] (%t:%x) %m%n

# 自定义编写的日志生成过滤类,每日生成且按固定大小分割
log4j.appender.FILE = com.osgc.dps.util.RoolingAndDateFileAppender
log4j.appender.FILE.Append = true
log4j.appender.FILE.Threshold = DEBUG
log4j.appender.FILE.File = ./logs/dpsInfo.log
log4j.appender.FILE.DatePattern = yyyy-MM-dd
log4j.appender.FILE.layout = org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=%d{yyyy-mm-dd HH24:mm:ss}-%-5r %-5p [%c] (%t:%x) - %m%n
# 单个文件的大小
log4j.appender.FILE.MaxFileSize=200MB
# 最大分割数量
log4j.appender.FILE.maxIndex=50
# 是否把非当日的文件清理到昨日文件夹中
log4j.appender.FILE.isCleanLog=true

## SQL的执行日志
log4j.logger.java.sql.PreparedStatement=DEBUG