springboot log4j2.yml 配置日志文件自动过期(只保留7天) 亲测可以!
线上出了一个奇怪的bug,上传文件部分请求出现500错误同一个文件上传,部分请求会出现500错误,部分返回正确的图片地址。环境:20台服务器的集群,Java jar程序经过排查发现是磁盘满了,参考之前我的文章如何排查磁盘100%发现一个令人大吃一惊的事情,每台机器是40G硬盘,日志文件占了32G,-,-至于为什么部分请求成功呢?因为20台还没有所有机器都满。首先肯定是删除一波日志文件解决问题,发现
问题
线上出了一个奇怪的bug,上传文件部分请求出现500错误
同一个文件上传,部分请求会出现500错误,部分返回正确的图片地址。
环境:20台服务器的集群,Java jar程序
经过排查发现是磁盘满了,参考之前我的文章
如何排查磁盘100%
发现一个令人大吃一惊的事情,每台机器是40G硬盘,日志文件占了32G,-,-
发现info的日志有几天的info.log文件有2G左右,这谁顶的住,应该是线上出了bug,然后疯狂打日志(内网环境没法复现)。
(解释一下不是我写的…)
至于为什么部分请求成功呢?因为20台还没有所有机器都满。
问题解决
首先肯定是删除一波日志文件解决问题
删除文件是解决了,但是不可能隔一段时间就上去删一下吧,程序员是不可能干这样的事情的,-。-,
最后肯定是需要定时删除下日志的,要么程序本身定时删除,要么定时脚本删除
(不推荐脚本删除,别人接收你的项目会发现联带的东西很多,很乱,尽量保持程序的专一和简洁,用行话叫 解耦
🎅🏽)
日志解决方案
直接说日志配置解决方案
Configuration:
Properties:
Property:
- name: log.path
value: /Users/admin/log/lib
- name: application.name
value: lib
Appenders:
RollingRandomAccessFile:
- name: infoRollingFile
ThresholdFilter:
level: error
onMatch: DENY
onMismatch: ACCEPT
fileName: ${log.path}/info.log
filePattern: ${log.path}/info.%d{yyyy-MM-dd}.log
PatternLayout:
Pattern: '[%d]\t%p\t[${application.name}]\t%c{1}\t%M\t[%t]\t[%X{reqId}]\t--\t%m%n'
Policies:
SizeBasedTriggeringPolicy:
size: 2M
TimeBasedTriggeringPolicy:
interval: 2
modulate: true
DefaultRolloverStrategy:
Delete:
IfFileName:
glob: "*log"
IfLastModified:
age: 1s
max: 3
- name: errorRollingFile
ThresholdFilter:
level: error
onMatch: ACCEPT
onMismatch: DENY
fileName: ${log.path}/err.log
filePattern: ${log.path}/err.%d{yyyy-MM-dd}.log
PatternLayout:
Pattern: '[%d]\t%p\t[${application.name}]\t%c{1}\t%M\t[%t]\t[%X{reqId}]\t--\t%m%n'
Policies:
SizeBasedTriggeringPolicy:
size: 1M
TimeBasedTriggeringPolicy:
interval: 1
modulate: true
DefaultRolloverStrategy:
max: 3
Delete:
basePath: ${log.path}
IfFileName:
glob: "*log"
IfLastModified:
age: 1s
Console:
name: console
PatternLayout:
Pattern: '[%d]\t%p\t[${application.name}]\t%c{1}\t%M\t[%t]\t[%X{reqId}]\t--\t%m%n'
target: SYSTEM_OUT
Loggers:
Root:
level: info
AppenderRef:
# - ref: console
- ref: infoRollingFile
- ref: errorRollingFile
上面是我测试使用的日志配置,可以实现过期日志文件自动删除,亲测可以! 但是里面的配置还是要按实际的来
核心讲解
log4j2本身就考虑到日志文件太大的问题,支持日志的限制和过期删除,但是百度的教程大部分是xml文件,是比较旧的教程,而且没有详细讲解参数的具体作用,只给出配置文件。
作为合格的程序员,当然要手动尝试一下,亲测才能推荐出来。(q.q)
核心配置
#清除策略
DefaultRolloverStrategy:
#删除的触发条件
Delete:
#要删除扫描的文件夹
basePath: ${log.path}
#限定扫描的文件名
IfFileName:
#匹配规则 以log结尾的
glob: "*log"
#文件的最新的修改时间间隔
IfLastModified:
#1s 表示1秒前 7d表示7天
age: 1s
踩坑记录
1、IfLastModified表示的是最新修改时间,一般是设置为7d,也就是7天,如果你测试日志删除也是配置7d,你会发现删除没有效果,因为你就算新建日志文件,名字取为info.2021-06-02.log
也不会删除,因为是你新创建的,修改时间小于7天,所以不执行删除。
2、basePath: ${log.path}
必须要,因为没有配置这个属性导致程序不确定你要扫描的文件夹,怕误删文件,所以不执行删除。这个坑是最大的坑,搞到这一步就算是成了。
3、xml配置转化为yml,部分xml教程里面应该是可以真的执行删除的,但是xml配置和yml文件不一样,比如
<DefaultRolloverStrategy max="3">
<Delete basePath="/Users/admin/log/lib/history" maxDepth="1">
<IfFileName glob="*.log.gz"/>
<IfLastModified age="3s"/>
</Delete>
</DefaultRolloverStrategy>
怎么转化为yml文件?又有属性又有子集,其实你把自己想象成开发者就好了,你觉得怎样写yml才和xml文件配置的逻辑一致?
max=3是DefaultRolloverStrategy属性,所以应该是子集
Delete是子集,和属性应该是平级(至少不是max的子集)
最后结论应该是
DefaultRolloverStrategy:
max: 3
Delete:
basePath: /Users/admin/log/lib/history
maxDepth: 1
IfFileName:
glob: "*.log.gz"
IfLastModified:
age: 3s
注意有些可以值可以不加"",但是有些明显是字符串的需要""标记为字符串,
直接写glob: .log.gz
会导致无法识别
4、 IfFileName 也是必要的,不要配置"*.log",因为会删除所有匹配的文件,比如error.log,可以配置为"info*.log"
ok,这样配置一下就可以实现自动删除了,而且你可以本地测试一下,用while打日志,比如你的日志是info.2021-07-02.log
名称,那你可以复制一下,名称改为info.2021-06-02.log
,然后启动测试类打印日志,你就会发现,满足条件的这个旧的日志自动删除了。
最后附上一个简单的测试类
@Test
public void base(){
StringBuffer buffer=new StringBuffer();
for (int i=0;i<100;i++){
buffer.append(i+"hello"+Math.random());
}
while (true){
/*try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
log.info("hello"+buffer.toString());
//log.error("hello"+Math.random());
}
}
更多推荐
所有评论(0)