SLF4J与Log4j2的完美配合
上一篇讲述了“Log4j、SLF4J、Logback、Log4j2” 的来龙去脉,本篇将着重说明“SLF4J+Log4j2”的使用。参照官网学习,建议从头看完,当然,直接拖到最后看完整的“配置+详细行注释”也可
1、到maven仓库找 SLF4J 相关的依赖,这里直接撸 1.7.36 版
https://mvnrepository.com/artifact/org.slf4j/slf4j-api
得到的坐标如下
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
2、到maven仓库找 Log4j2 相关的依赖
https://mvnrepository.com/artifact/org.apache.logging.log4j
得到的坐标如下
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-web -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.17.2</version>
</dependency>
另外,异步需要依赖下述的jar
<!-- https://mvnrepository.com/artifact/com.lmax/disruptor -->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.4.2</version>
</dependency>
3、综上,总共需要的jar的坐标如下
<!-- slf4j的依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<!-- log4j的核心包 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.2</version>
</dependency>
<!-- log4j与slf4j绑定的依赖 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.2</version>
</dependency>
<!-- log4j对web项目的支持 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.17.2</version>
</dependency>
<!-- 实现异步的依赖 -->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.4.2</version>
</dependency>
4、在项目中配置
https://logging.apache.org/log4j/2.x/manual/configuration.html
注意!直接在resource目录下配置 log4j2.xml 配置文件 (注意,如果文件名不叫 log4j2.xml ,那么还需要在 web.xml中指定配置文件路径)
先了解下配置文件中的几个关键节点:
1、Configuration - 配置文件最外层的节点
<Configuration name="ConfigTest" status="ERROR" monitorInterval="5">
</Configuration>
name:当前配置文件的名称
status:Log4j内部事件的级别。有效值为“off”、“trace”、“debug”、“info”、“warn”、“error”、“fatal”和“all”。Log4j 会将有关初始化等一些内部操作的详细信息打印出来(trace,如果需要排查log4j自身问题,可以配置成这个)
2、Appenders - 将日志输出到指定地方,同时可以配置打印的策略、格式等
(1)日志输出到文件中(File)
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
<Appenders>
<File name="MyFile" fileName="logs/app.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="MyFile"/>
</Root>
</Loggers>
</Configuration>
(2)日志输出到 Apache Cassandra 数据库(Cassandra)
<Configuration name="CassandraAppenderTest">
<Appenders>
<Cassandra name="Cassandra" clusterName="Test Cluster" keyspace="test" table="logs" bufferSize="10" batched="true">
<SocketAddress host="localhost" port="9042"/>
<ColumnMapping name="id" pattern="%uuid{TIME}" type="java.util.UUID"/>
<ColumnMapping name="timeid" literal="now()"/>
<ColumnMapping name="message" pattern="%message"/>
<ColumnMapping name="level" pattern="%level"/>
<ColumnMapping name="marker" pattern="%marker"/>
<ColumnMapping name="logger" pattern="%logger"/>
<ColumnMapping name="timestamp" type="java.util.Date"/>
<ColumnMapping name="mdc" type="org.apache.logging.log4j.spi.ThreadContextMap"/>
<ColumnMapping name="ndc" type="org.apache.logging.log4j.spi.ThreadContextStack"/>
</Cassandra>
</Appenders>
<Loggers>
<Logger name="org.apache.logging.log4j.cassandra" level="DEBUG">
<AppenderRef ref="Cassandra"/>
</Logger>
<Root level="ERROR"/>
</Loggers>
</Configuration>
(3)日志输出到控制台(Console)
<Configuration status="warn" name="MyApp" packages="">
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%m%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
(4)滚动文件输出(RollingFile)
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
<Appenders>
<RollingFile name="RollingFile" fileName="logs/app.log"
filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="250 MB"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
(5)滚动文件输出完整版及释义
这里说几个关键的参数
append:默认为true。表示新记录写入时,是在原文件内容基础上追加,还是清除之前的
bufferedIO:默认为true。表示新记录会先写入缓冲区,当缓冲区数据满了之后,再将数据转移到磁盘上,这种方式可以提高性能
bufferSize:缓冲区大小,默认为8192字节 (注意,bufferedIO为true时,才会用到这个)
fileName:要写入的文件路径,如果文件不存在,会直接创建
immediateFlush:默认为true。每次写入数据后都会刷新。如果设置为false的话,日志会先放在缓冲区,那么最终写入到文件中时,可能存在延迟
policy:日志存档的策略,比如日志文件达到多大时,或者到达什么时间时
<Configuration name="MyApp" status="ERROR" monitorInterval="5">
<Properties>
<Property name="baseDir">logs</Property>
</Properties>
<Appenders>
<RollingFile name="RollingFile" fileName="${baseDir}/app.log"
filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
<PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="250 MB"/>
</Policies>
<DefaultRolloverStrategy max="100">
<Delete basePath="${baseDir}" maxDepth="2">
<IfFileName glob="*/app-*.log.gz">
<IfLastModified age="P30D">
<IfAny>
<IfAccumulatedFileSize exceeds="100 GB" />
<IfAccumulatedFileCount exceeds="10" />
</IfAny>
</IfLastModified>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
上面的意思是:
日志路径为:logs/app.log (此处省略了应用部署的路径,直接按照上诉配置的话,路径是在tomcat的bin目录中)
当文件达到250MB时 或者 过了6个小时,则会产生一个新文件
历史文件会放入目录(这里以当前时间举例):logs/2022-05 历史文件会被压缩,完整文件名为:app-2022-05-08-22-1.log.gz、app-2022-05-08-22-2.log.gz
<DefaultRolloverStrategy max="100"> 这里的 max="100" 表示同一天存档文件最多100个,到达100个时,会删除之前的
<Delete basePath="${baseDir}" maxDepth="2"> 表示要删除文件所在的目录
<IfFileName glob="*/app-*.log.gz"> 表示要删除的文件,文件名需符合 */app-*.log.gz 这种格式
<IfLastModified age="P30D"> 表示删除30天以前的文件
<IfAccumulatedFileSize exceeds="100 GB" /> 表示,如果文件内容达到100GB,那么此文件不删除
<IfAccumulatedFileCount exceeds="10" /> 表示,最近的10个文件不删除
3、Loggers - 日志打印的配置
这里的设置与上面的<Appenders>配置对应,注意观察这里
Loggers 中用来配置Appenders中日志的级别,当有多个Appenders时,对应也可以配置多个AppenderRef,如下
<Loggers>
<Root>
<AppenderRef ref="RollingFile" level="info"/>
<AppenderRef ref="Console" level="debug"/>
</Root>
</Loggers>
4、在代码中直接使用即可
!!注意引入的时候,引入slf4j相关的包
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Test {
private static Logger logger = LoggerFactory.getLogger(Test.class);
public static void main(String[] args) {
String str = "哈哈";
logger.info("测试打日志,{}",str);
}
}
5、给出一个完整的配置(带注释)
参考
log4j2的官网
https://logging.apache.org/log4j/2.x/