日志框架是用来生成、输出、存储和管理日志的工具。
门面日志框架是一种为了简化日志框架使用而设计的中间层。
它提供了一种简单的方式来记录日志,而无需了解底层的日志框架的实现细节。门面日志框架可以将日志记录的实现与应用程序分离,从而使得应用程序更加可维护和可扩展。另外,门面日志框架还可以提供一些高级功能,如日志级别控制、日志过滤等,以进一步简化日志记录的过程。
日志 ⇒ slf4j+log4j2
log4j2(有三种模式[全异步、混合异步、同步])的性能吊打log4j1和logback。
尤其在[多线程的测试下,log4j2的性能更是火力全开。
所以,为了实现更好的日志打印,我们就选择log4j2即可。
log4j2日志性能比较:全异步>混合异步>同步。
完全异步日志打印方式是性能最高的方式,也是官方推荐的方式。所以建议在使用的时候使用全异步的方式。
异步日志的意义
异步日志是一种日志记录的方式,它可以显著提升代码运行的速度,尤其在涉及大量日志记录的情况下。异步日志的主要作用是减少对代码性能的影响,从而提高程序的执行效率。
传统的同步日志记录方式会在日志语句执行时直接将日志写入日志文件,这可能会导致程序在执行日志记录时发生阻塞,从而降低程序的性能。特别是在高并发的情况下,频繁的日志写入可能会对程序的整体性能产生较大的影响。
异步日志则是将日志记录操作放入一个独立的线程中进行处理,这个线程负责将日志写入到日志文件。这样,程序的主线程不会因为日志记录而被阻塞,继续执行其他任务,从而提高了程序的运行效率。当然,这并不意味着异步日志记录不需要消耗任何资源,因为还需要启动和管理一个额外的线程来处理日志。
总之,异步日志的作用在于降低日志记录对程序性能的影响,从而提高代码的运行速度,特别是在需要频繁进行日志记录的场景下。
完全异步日志打印方式是性能最高的方式,也是官方推荐的方式。
1、添依赖log4j-slf4j-impl
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.2</version>
</dependency>
<!--异步日志依赖 暂时可以不加-->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.4</version>
</dependency>
- 日志语句输出
Logger logger = LoggerFactory.getLogger(slf4jTest.class.getName());
slf4jTest.class.getName()
一般此处直接获取当前类的名称即可,日志输出时会打印当前类为com.project.log4j.slf4jTest
。
2、log4j2.xml配置:修改日志输出路径Log home即可
-
xml配置代码
<?xml version="1.0" encoding="UTF-8"?> <Configuration> <!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出--> <!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数--> <!--<Configuration status="WARN" monitorInterval="50"> --> <properties> <property name="LOG_HOME">D:\learnCodeLib22\测试代码\log4j2demo\logs</property> <property name="LOG_PATTERN" value="%d %p %c [%t] %m%n"/> </properties> <Appenders> <!--*********************控制台日志***********************--> <Console name="consoleAppender" target="SYSTEM_OUT"> <!--设置日志格式及颜色--> <PatternLayout pattern="${LOG_PATTERN}" noConsoleNoAnsi="false"/> </Console> <!--*********************文件日志***********************--> <!--all级别日志--> <RollingFile name="allFileAppender" fileName="${LOG_HOME}/all.log" filePattern="${LOG_HOME}/$${date:yyyy-MM}/all-%d{yyyy-MM-dd}-%i.log.gz"> <!--设置日志格式--> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <!-- 设置日志文件切分参数 --> <!--<OnStartupTriggeringPolicy/>--> <!--设置日志基础文件大小,超过该大小就触发日志文件滚动更新--> <SizeBasedTriggeringPolicy size="100 MB"/> <!--设置日志文件滚动更新的时间,依赖于文件命名filePattern的设置--> <TimeBasedTriggeringPolicy/> </Policies> <!--设置日志的文件个数上限,不设置默认为7个,超过大小后会被覆盖;依赖于filePattern中的%i--> <DefaultRolloverStrategy max="100"/> </RollingFile> <!--debug级别日志--> <RollingFile name="debugFileAppender" fileName="${LOG_HOME}/debug.log" filePattern="${LOG_HOME}/$${date:yyyy-MM}/debug-%d{yyyy-MM-dd}-%i.log.gz"> <Filters> <!--过滤掉info及更高级别日志--> <ThresholdFilter level="info" onMatch="DENY" onMismatch="NEUTRAL"/> </Filters> <!--设置日志格式--> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <!-- 设置日志文件切分参数 --> <!--<OnStartupTriggeringPolicy/>--> <!--设置日志基础文件大小,超过该大小就触发日志文件滚动更新--> <SizeBasedTriggeringPolicy size="100 MB"/> <!--设置日志文件滚动更新的时间,依赖于文件命名filePattern的设置--> <TimeBasedTriggeringPolicy/> </Policies> <!--设置日志的文件个数上限,不设置默认为7个,超过大小后会被覆盖;依赖于filePattern中的%i--> <DefaultRolloverStrategy max="100"/> </RollingFile> <!--info级别日志--> <RollingFile name="infoFileAppender" fileName="${LOG_HOME}/info.log" filePattern="${LOG_HOME}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz"> <Filters> <!--过滤掉warn及更高级别日志--> <ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL"/> </Filters> <!--设置日志格式--> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <!-- 设置日志文件切分参数 --> <!--<OnStartupTriggeringPolicy/>--> <!--设置日志基础文件大小,超过该大小就触发日志文件滚动更新--> <SizeBasedTriggeringPolicy size="100 MB"/> <!--设置日志文件滚动更新的时间,依赖于文件命名filePattern的设置--> <TimeBasedTriggeringPolicy/> </Policies> <!--设置日志的文件个数上限,不设置默认为7个,超过大小后会被覆盖;依赖于filePattern中的%i--> <DefaultRolloverStrategy max="100"/> </RollingFile> <!--warn级别日志--> <RollingFile name="warnFileAppender" fileName="${LOG_HOME}/warn.log" filePattern="${LOG_HOME}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz"> <Filters> <!--过滤掉error及更高级别日志--> <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/> </Filters> <!--设置日志格式--> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <!-- 设置日志文件切分参数 --> <!--<OnStartupTriggeringPolicy/>--> <!--设置日志基础文件大小,超过该大小就触发日志文件滚动更新--> <SizeBasedTriggeringPolicy size="100 MB"/> <!--设置日志文件滚动更新的时间,依赖于文件命名filePattern的设置--> <TimeBasedTriggeringPolicy/> </Policies> <!--设置日志的文件个数上限,不设置默认为7个,超过大小后会被覆盖;依赖于filePattern中的%i--> <DefaultRolloverStrategy max="100"/> </RollingFile> <!--error及更高级别日志--> <RollingFile name="errorFileAppender" fileName="${LOG_HOME}/error.log" filePattern="${LOG_HOME}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz"> <!--设置日志格式--> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <!-- 设置日志文件切分参数 --> <!--<OnStartupTriggeringPolicy/>--> <!--设置日志基础文件大小,超过该大小就触发日志文件滚动更新--> <SizeBasedTriggeringPolicy size="100 MB"/> <!--设置日志文件滚动更新的时间,依赖于文件命名filePattern的设置--> <TimeBasedTriggeringPolicy/> </Policies> <!--设置日志的文件个数上限,不设置默认为7个,超过大小后会被覆盖;依赖于filePattern中的%i--> <DefaultRolloverStrategy max="100"/> </RollingFile> </Appenders> <Loggers> <!-- 根日志设置 --> <Root level="debug"> <AppenderRef ref="allFileAppender" level="all"/> <AppenderRef ref="consoleAppender" level="debug"/> <AppenderRef ref="debugFileAppender" level="debug"/> <AppenderRef ref="infoFileAppender" level="info"/> <AppenderRef ref="warnFileAppender" level="warn"/> <AppenderRef ref="errorFileAppender" level="error"/> </Root> </Loggers> </Configuration>
-
配置代码详解
<property >
<property name="LOG_HOME">D:\learnCodeLib22\测试代码\log4j2demo\logs</property>
: 定义了一个名为 “LOG_HOME” 的属性,表示日志输出的文件夹路径。<property name="LOG_PATTERN" value="%d %p %c [%t] %m%n"/>
: 定义了一个名为 “LOG_PATTERN” 的属性,表示日志输出的格式。- 其中
%d
表示日期时间,%p
表示日志级别,%c
表示日志类名,%t
表示线程名,%m
表示日志消息,%n
表示换行。 - log4j2.xml按照时间进行日志压缩打包
<Appenders>
: 在这里定义了日志的输出目标。<Console name="consoleAppender" target="SYSTEM_OUT">
: 定义了一个输出到控制台的 Appender,名为 “consoleAppender”。<RollingFile name="allFileAppender" ...>
: 定义了一个输出到文件的 Appender,名为 “allFileAppender”。这里使用了滚动文件输出,即会自动按照一定条件滚动日志文件,防止文件过大。fileName="${LOG_HOME}/all.log"
: 日志文件的输出路径。filePattern="${LOG_HOME}/$${date:yyyy-MM}/all-%d{yyyy-MM-dd}-%i.log.gz"
: 日志文件的滚动规则。<PatternLayout pattern="${LOG_PATTERN}"/>
: 使用之前定义的日志格式。<Policies> ... </Policies>
: 设置触发滚动的策略,包括文件大小和时间。
<Loggers>
: 配置日志的记录器。<Root level="debug">
: 根日志记录器的设置,这里设置了日志级别为 “debug”。<AppenderRef ref="..." level="..."/>
: 引用不同的 Appender 并设置级别,指定了不同级别的日志将会被输出到不同的 Appender。
控制台输出语句高亮显示需要插件支持 Grep console
3、异步日志依赖
<!--异步日志依赖 暂时可以不加-->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.4</version>
</dependency>
4、完全异步开启: 通过配置文件 log4j2.component.properties [推荐方案]
新建一个文件 log4j2.component.properties
Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
5、验证异步是否开启
验证异步日志开启的唯一方式, 也是最准确的方式,
测试非日志输出代码和日志输出代码是否按顺序执行
System.out.println(" 业务代码1 ");
log.info("name = {}, password = {}",name,password);
System.out.println(" 业务代码2 ");
输出结果:
业务代码1
业务代码2
name = xxx, password = 123
6、热加载
<Configuration monitorInterval="5">
monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数
注意: 热加载的时候不是修改源码配置文件, 而是编译区域的配置文件(.class文件)
通过注解使用:@Slf4j注解 会自动生成一个log对象
在类上面添加@Slf4j
,之后直接使用log.info
等命令即可
log.info("name = {}, password = {}",name,password);
一次性输出三个时需要使用数组new Object[]{}
log.info("保存角色关系··· roleID = {}, selectuser = {}, selectoper = {}",new Object[]{roleID, Arrays.toString(selectuser), Arrays.toString(selectoper)});