log4j 系列08 -- SSM 框架下 slf4j-log4j 升级 slf4j-log4j2,实现日志定时清理【有踩坑记录】

10 篇文章 0 订阅

官方参考文档:http://logging.apache.org/log4j/2.x/javadoc.html

公司上一个系统(SSM框架),在测试服务器上(硬盘空间较小)运行差不多半个月之后突然访问不了,一查原因是磁盘空间被占满,再仔细一查大文件,原来是日志堆积太多,又没有定期清理造成的。

第一个想法是,在 Linux 系统下写一个开机启动脚本,该脚本负责定时清理特定目录下的日志文件。网上搜了一下,命令还有点复杂(主要是我太菜了),若是认真研究个两三天倒是也能搞定,时间宝贵,能不能从 log4j 本身入手呢?

============正文开始=============

log4j  本身没有定时清理日志功能,但可以通过自定义 Appender 实现; log4j2  自带定时清理日志功能,且 log4j2 还有其他高级功能,各方面性能均优于 log4j,那还犹豫个JB毛,拉上 log4j2 就开干啊!

【关键点: POM.xml  和  web.xml   的修改

目录

第一部分:POM.xml  和  web.xml  的改造

1、POM 依赖 改造

(1)、删除之前的  slf4j-log4j 依赖

(2)、添加  slf4j-log4j2 依赖

2、web.xml 改造 【踩坑】

(1)、Servlet 版本升级

(2)、删除 Log4jConfigListener 

(3)、设置配置文件位置

第二部分:log4j2.xml  的配置

(1)、onMatch 和 onMismatch 属性

(2)、不同级别日志输出到不同日志文件

(3)、定时清理日志 配置 Demo


第一部分:POM.xml  和  web.xml  的改造

参考:https://www.cnblogs.com/new-life/p/9246246.html
https://www.cnblogs.com/yoyotl/p/4920073.html
https://stackoverflow.com/questions/36683852/log4j-error-noclassdeffounderror-org-apache-log4j-xml-domconfigurator
 

1、POM 依赖 改造

(1)、删除之前的  slf4j-log4j 依赖

<!-- slf4j-log4j 配置--弃用 改用下面的 slf4j-log4j2 -->
<!-- 
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>1.7.9</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-log4j12</artifactId>
	<version>1.7.9</version>
</dependency> 
-->

(2)、添加  slf4j-log4j2 依赖

<!-- slf4j-log4j2 配置  -->
<!-- 首先引入slf4j的核心包 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>${slf4j.version}</version>
</dependency>

<!-- 然后引入slf4j对应log4j2的中间件 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>${log4j.version}</version>
</dependency>

<!-- 然后引入log4j2包 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>${log4j.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>${log4j.version}</version>
</dependency>


<!-- 最后引入另外两个相关的包 -->
<!--用于解决web环境下关闭服务器时可能出现的log4j线程无法及时关闭的warn,web工程需要包含log4j-web,非web工程不需要 -->
<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-web</artifactId>
	<scope>runtime</scope>
	<version>${log4j.version}</version>
</dependency>

<!--使用log4j2的AsyncLogger时需要包含disruptor -->
<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <scope>runtime</scope>
    <version>3.4.2</version>
</dependency>

<!-- 最后只需要在项目的resources目录下新建一个log4j2.xml作为log4j2的配置文件即可在项目中使用slf4j输出日志  -->

2、web.xml 改造 【踩坑】

(1)、Servlet 版本升级

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns="http://java.sun.com/xml/ns/javaee"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
     version="2.5">

看到了吧,将【2_5】改为【3_0】,将【2.5】改为【3.0】。

(2)、删除 Log4jConfigListener 

这个坑搞了我一个上午,项目启动时老报错:Log4j error: NoClassDefFoundError: org/apache/log4j/xml/DOMConfigurator
直到搜到  stackOverflow上的答案

(3)、设置配置文件位置

  • 日志配置文件默认读取路径为src/main/resource
  • 若文件放置在默认读取路径下则无需配置读取路径
  • 若文件放置到其他路径下则需要在web.xml中设置日志配置文件的读取路径,代码如下:
<context-param>
   <param-name>log4jConfiguration</param-name>
   <param-value>classpath:log4j2.xml</param-value>
</context-param>

关于  log4j2 的配置文件有一点需要注意:很多博客上说,log4j 2.x 版本不再支持像1.x中的.properties后缀的文件配置方式,这是错误的,可能是作者当时写博客的时候还不支持。从 log4j2.4 版本之后就支持.properties 配置方式了。(本文选择了XML配置方式)
详见官方文档: http://logging.apache.org/log4j/2.x/manual/configuration.html

第二部分:log4j2.xml  的配置

此部分参考文章:

聊一聊log4j2配置文件log4j2.xml

log4j2的xml配置,不同级别日志输出到不同日志文件

Log4j2的onMatch和onMismatch属性值详解

log4j2.xml 配置文件详解

log4j2 RollingFile用法 : 日志按天分,按小时分,按分钟分,按秒分;按大小分;自动(定时)清理

https://blog.csdn.net/cxy1991xm/article/details/90549806

https://blog.csdn.net/zhang168/article/details/46814489

https://www.jianshu.com/p/c6d9b418e433

配置的细节太多,都在参考文章里,不再赘述。这里记录一个关键点:onMatch 和 onMismatch 属性

(1)、onMatch 和 onMismatch 属性

<!--日志优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->

onMatch="ACCEPT" 表示匹配该级别及以上
onMatch="DENY" 表示不匹配该级别及以上
onMatch="NEUTRAL" 表示该级别及以上的,由下一个filter处理,如果当前是最后一个,则表示匹配该级别及以上

-- onMatch 相当于数学上的的 >=  (包含自身)


onMismatch="ACCEPT" 表示匹配该级别以下
onMismatch="NEUTRAL" 表示该级别以下的,由下一个filter处理,如果当前是最后一个,则不匹配该级别以下的
onMismatch="DENY" 表示不匹配该级别以下的

-- onMismatch 相当于数学上的的 <

(2)、不同级别日志输出到不同日志文件

debug 输出到 debug.log , info 输出到 info.log , >= WARN 输出到 error.log , 

<File name="app_debug" fileName="${log-path}/app/debug.log" append="false">
    <Filters>
	<ThresholdFilter level="info" onMatch="DENY" onMismatch="NEUTRAL"/>
	<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
    </Filters>
    <PatternLayout pattern="%d{yyyy.MM.dd HH:mm:ss z} %-5level %class{36}.%M()/%L - %msg%xEx%n"/>
</File>

<File name="app_info" fileName="${log-path}/app/info.log" append="false">
    <Filters>
	<ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL"/>
	<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
    </Filters>
    <PatternLayout pattern="%d{yyyy.MM.dd HH:mm:ss z} %-5level %class{36}.%M()/%L - %msg%xEx%n"/>
</File>

<File name="app_error" fileName="${log-path}/app/error.log" append="false">
    <Filters>
	<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
    </Filters>
    <PatternLayout pattern="%d{yyyy.MM.dd HH:mm:ss z} %-5level %class{36}.%M()/%L - %msg%xEx%n"/>
</File>

level总结:Appender 和 Logger 两个 地方都可以限制 level。

  • Logger 这里只有 >= ,
  • Appender 那里有 >= 和 < ,且可链式过滤

(3)、定时清理日志 配置 Demo

<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->

<configuration status="DEBUG" monitorInterval="30">

	<Properties>
	   <Property name="log-path">${sys:catalina.home}/logs</Property>
	</Properties>


	<appenders>
	  
	  <console name="Console" target="SYSTEM_OUT">
	     	<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} -%-4r [%t] %-5p  %x - %m%n"/>
	  </console>
	
	  <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用-->
	  <File name="log" fileName="${log-path}/test.log" append="false">
	  		<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
	  		<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
	  </File>
	  
	  <!-- 按秒记录日志,日志保留10秒   -->
	  <!-- 坑:1、fileName,filePattern,Delete basePath 都要写成绝对路径   -->
	  <!-- 坑:2、maxDepth 在 basePath 之下有几级目录就写几   -->
	  <!-- 坑:3、IfFileName 不需要斜线   -->
	  <RollingFile name="A" fileName="${log-path}/test_log/test_" filePattern="${log-path}/test_log/%d{yyyy-MM-dd-HH-mm-ss}.log">
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] [%-5p] %l - %m%n"/>
            
            <Policies>
                <TimeBasedTriggeringPolicy modulate="true" interval="1"/>
            </Policies>
            
            <DefaultRolloverStrategy max="20">
                <Delete basePath="${log-path}/test_log" maxDepth="1">
                    <IfFileName glob="*.log" />
                    <IfLastModified age="10s" />
                </Delete>
            </DefaultRolloverStrategy>
       </RollingFile> 

	</appenders>


	<loggers>
	
		<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
		<logger name="org.springframework" level="INFO"></logger>
		<logger name="org.mybatis" level="INFO"></logger>
		<logger name="java.sql" level="INFO"></logger>
	
        <root level="DEBUG">
		     <appender-ref ref="Console"/>
		     <appender-ref ref="log"/>
		     <appender-ref ref="A"/>
		</root>
		 
	</loggers>
	
</configuration>


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值