介绍
日志概述
只要程序员投身在实际的学习和生产环境中,就会对日志的重要性有着充分的认知,尤其是对于 Web 以及更高级的应用。在很多情况下,日志可能是我们了解应用如何执行的唯一方式。
但是现实是很多程序员对于日志的记录的认知比较肤浅,认为日志的记录输出是一件很简单而且会自动发生的事情,所以会经常忽略和日志相关的问题。
所以本课程主要就是针对于对于日志概念以及日志的框架不太熟悉的这类开发人群,更加详细且真实的体会日志为我们在开发和生产环境当中所带来的好处。
Java 语言的强大之处就是因为它强大而且成熟的生态体系。其中包括日志框架,就有很多成熟的开源资源可以直接使用。
日志文件
日志文件是用于记录系统操作事件的文件集合。它具有处理历史数据、诊断问题的追踪以及理解系统的活动等重要的作用。
调试日志
在软件开发中,我们要去经常的调试程序,或者做一些状态的输出,便于我们查询程序的运行状况。为了让我们能够更加灵活且方便的控制这些调试信息,我们肯定是需要更加专业的日志技术。我们平时在调试程序的过程中所使用的肯定就是专业开发工具自带的debug功能,可以实时查看程序运行情况,但不能有效保存运行情况的信息。调试日志是能够更加方便的去“重现”这些问题。
系统日志
系统日志是用来记录系统中硬件、软件和系统相关问题的信息。同时还可以监视系统中发生的事件。用户可以通过它来检查错误发生的原因,或者寻找收到攻击是留下的痕迹。
系统日志包括系统日志、应用日志和安全日志这几种分类。
日志框架
日志框架的作用
- 控制日志输出的内容和格式。
- 控制日志输出的位置。
- 日志文件相关的优化,如异步操作、归档、压缩..
- 日志系统的维护。
- 面向接口开发 - 日志的门面。
日志框架的价值
因为软件系统发展到了今天非常的复杂,特别是服务器的软件,涉及到的知识和内容问题非常的多。对于日志记录来讲,在某些方面使用别人研发好的成熟的框架,这就相当于让别人帮你完成一些基础的工作。让我们可以有更多的时间去关注、处理我们的业务逻辑问题。
比如事务处理,日志记录等一些安全性的问题,我们使用框架丢做,不会影响业务的开发效率。
同时框架也是在不断升级的,我们可以不断的享受框架为我们带来的好处。
流行的日志框架
- JUL
java.util.logging JAVA原生日志框架
- Log4j
Apache的一个开源项目
- Logback
由Log4j之父做的另一个开源项目,业界称之为log4j后浪,一个可靠、通用且灵活的java日志框架
- Log4j2
Log4j官方的第二个版本,各个方面都与Logback及其相似,具有插件式结构、配置文件优化等特征。SpringBoot1.4版本以后就不再支持log4j,所以第二个版本——log4j2应运而生。
- JCL
日志门面
- SLF4J
日志门面
SLF4J日志门面
介绍
简单日志门面(Simple Logging Facade For Java)SLF4J主要是为了给Java日志访问提供一套标准、规范的API框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架,例如 log4j和 logback等。当然slf4j自己也提供了功能较为简单的实现,但是一般很少用到。对于一般的Java项目而言,日志框架会选择slf4j-api作为门面,配上具体的实现框架(log4j、logback等),中间使用桥接器完成桥接。所以我们可以得出 SLF4J最重要的两个功能就是对于日志框架的绑定以及日志框架的桥接。
环境搭建简单测试
引入依赖
<!--slf4j核心依赖--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.25</version></dependency><!--slf4j自带简单日志实现--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>1.7.25</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency>
测试日志
可以看到只打印了info和error信息,因为slf4j的默认日志打印级别就是info级
集成log4j
下面使用log4j实现来进行日志的打印
导入log4j所需依赖,注意要注释掉之前得slf4j自带的简单实现依赖
logback
Logback简介
Logback 是由 log4j 创始人设计的又一个开源日志组件。
Logback 当前分成三个模块: logback-core,logback-classic和logback-access。
logback-core 是其它两个模块的基础模块。
logback-classic 是 log4j的一个改良版本。此外 logback-classic 完整实现SLF4J API。使你可以很方便地更换成其它日志系统如 log4j或JDK14 Logging。
logback-access 访问模块与 Servlet 容器集成提供通过 Http 来访问日志的功能。
Logback中的组件
- Logger:日志的记录器,
主要用于存放日志对象,也可以定义日志类型、级别。
- Appender:用于指定日志输出的目的地,目的地可以是控制台、文件、数据库等等。
- Layout:负责把事件转换成字符串,格式化的日志信息的输出。在Logback 中Layout 对象被封装在 encoder 中.也就是说我们未来使用的 encoder 其实就是 Layout
Logback配置文件
Logback提供了3种配置文件。
- logback.groovy
- logback-test.xml
- logback.xml
如果都不存在则采用默认的配置。
日志输出格式
标识符及占位符 | 描述 |
%-10level | 级别,设置10个这符,左对齐 |
%d{yyyy-MM-dd HH:mm:ss.SSS} | 日期时间 |
%c | 当前类全限定名 |
%M | 当前执行日志的方法 |
%L | 行号 |
%thread | 线程名称 |
%m或者%msg | 输出的日志信息 |
%n | 换行 |
控制台输出日志
引入所需依赖
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version></dependency><!--slf4j日志门面 核心依赖--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.32</version></dependency><!--logback-core是logback-classic的基础模块logback-classic已经涵盖了 logback-core,Maven有依赖传递性,会自动依赖logback-core--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.10</version></dependency>
在资源目录下新建xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<configuration><!--<property name="" value=""></property>配置文件通用属性,通过${name}的形式取值--><property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] 日志级别:[%-5level] %c %M %L %m%n"></property><!-- 控制台Appender --><appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"><!--输出目标的配置,System.out:以黑色字体(默认)System.err:红色字体--><target>System.err</target><!-- 日志输出格式 --><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><!--日志记录器配置,可以配置多个Appender,进行多方向的日志输出root => rootLoggerlevel: 表示日志级别--><root level="ALL"><appender-ref ref="consoleAppender"/></root></configuration>
测试:
输出日志到指定普通文件
我们在部署项目到服务器里通常都是直接通过日志文件进行查看日志的,而这时就需要将日志信息输出到指定位置的指定文件中
添加输出日志文件配置
<?xml version="1.0" encoding="UTF-8" ?>
<configuration><!--<property name="" value=""></property>配置文件通用属性,通过${name}的形式取值--><property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] 日志级别:[%-5level] %c %M %L %m%n"></property>
<!-- 日志文件输出路径--><property name="logDir" value="D:/javaPro/log/logback/log"></property>
<!-- 保存的日志文件名--><property name="fileName" value="logback.log"></property><!--文件appender,默认是以追加日志的形式进行输出的--><appender name="fileAppender" class="ch.qos.logback.core.FileAppender"><!--输出文件位置--><file>${logDir}//${fileName}</file><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><!-- 控制台Appender --><appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"><!--输出目标的配置,System.out:以黑色字体(默认)System.err:红色字体--><target>System.err</target><!-- 日志输出格式 --><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><!--日志记录器配置,可以配置多个Appender,进行多方向的日志输出root => rootLoggerlevel: 表示日志级别--><root level="ALL"><appender-ref ref="consoleAppender"/><appender-ref ref="fileAppender"/></root></configuration>
启动测试:
来到xml文件中配置的文件输出位置
可以看到控制台的日志信息已经输出到logback.log文件中了,此时再重启测试,观察日志文件信息的变化:
可以看到日志信息是默认进行追加,不是覆盖
输出日志到html文件
在输出日志时,还可以将日志文件输出为html文件,来进行可读性比较好的阅读
<?xml version="1.0" encoding="UTF-8" ?>
<configuration><!--<property name="" value=""></property>配置文件通用属性,通过${name}的形式取值--><property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] 日志级别:[%-5level] %c %M %L %m%n"></property>
<!-- 日志文件输出路径--><property name="logDir" value="D:/javaPro/log/logback/log"></property>
<!-- 保存的日志文件名--><property name="fileName" value="logback.log"></property><!--文件appender,默认是以追加日志的形式进行输出的--><appender name="fileAppender" class="ch.qos.logback.core.FileAppender"><!--输出文件位置--><file>${logDir}//${fileName}</file><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><property name="htmlFileName" value="logback.html"></property><property name="htmlPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}%thread%-5level%c%M%L%m"></property><!--HTML文件appender--><appender name="htmlFileAppender" class="ch.qos.logback.core.FileAppender"><!--输出文件位置--><file>${logDir}//${htmlFileName}</file><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="ch.qos.logback.classic.html.HTMLLayout"><pattern>${htmlPattern}</pattern></layout></encoder></appender><!-- 控制台Appender --><appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"><!--输出目标的配置,System.out:以黑色字体(默认)System.err:红色字体--><target>System.err</target><!-- 日志输出格式 --><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><!--日志记录器配置,可以配置多个Appender,进行多方向的日志输出root => rootLoggerlevel: 表示日志级别--><root level="ALL"><appender-ref ref="consoleAppender"/><appender-ref ref="fileAppender"/><appender-ref ref="htmlFileAppender"/></root></configuration>
启动测试:
可以看到html版本的日志文件可读性和ui要比普通文件要美观一些,但是html文件比较占用内存,所以在实际开发中,如果项目的日志文件比较多的情况下并不推荐使用html版
日志文件拆分
在实际开发中,项目的日志有时候会非常的多,此时日志文件如果不进行拆分将会导致日志文件过大,有时甚至上G,所以可以对日志进行配置拆分策略来进行解决
<?xml version="1.0" encoding="UTF-8" ?>
<configuration><!--<property name="" value=""></property>配置文件通用属性,通过${name}的形式取值--><property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] 日志级别:[%-5level] %c %M %L %m%n"></property>
<!-- 日志文件输出路径--><property name="logDir" value="D:/javaPro/log/logback/log"></property>
<!-- 保存的日志文件名--><property name="fileName" value="logback.log"></property><!--文件appender,默认是以追加日志的形式进行输出的--><appender name="fileAppender" class="ch.qos.logback.core.FileAppender"><!--输出文件位置--><file>${logDir}//${fileName}</file><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><property name="htmlFileName" value="logback.html"></property><property name="htmlPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}%thread%-5level%c%M%L%m"></property><!--HTML文件appender--><appender name="htmlFileAppender" class="ch.qos.logback.core.FileAppender"><!--输出文件位置--><file>${logDir}//${htmlFileName}</file><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="ch.qos.logback.classic.html.HTMLLayout"><pattern>${htmlPattern}</pattern></layout></encoder></appender><!-- 控制台Appender --><appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"><!--输出目标的配置,System.out:以黑色字体(默认)System.err:红色字体--><target>System.err</target><!-- 日志输出格式 --><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><!--可拆分归档的appender--><appender name="rollFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder><file>${logDir}/roll_logback.log</file><!--指定拆分规则--><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!--按照时间和压缩格式声明文件名,压缩格式gz--><fileNamePattern>${logDir}/roll_logback.%d{yyyy-MM-dd}.log%i.gz</fileNamePattern><!--按照文件大小进行拆分--><maxFileSize>2KB</maxFileSize></rollingPolicy></appender><!--日志记录器配置,可以配置多个Appender,进行多方向的日志输出root => rootLoggerlevel: 表示日志级别--><root level="ALL"><appender-ref ref="consoleAppender"/><appender-ref ref="fileAppender"/><appender-ref ref="htmlFileAppender"/><appender-ref ref="rollFileAppender"/></root></configuration>
此时在测试中书写一个for循环来进行模拟业务非常多的数据
启动测试:
查看gz压缩文件
可以看到日志文件已经进行自动拆分了,当日志文件达到2kb大小时就可以进行正常的拆分
过滤日志等级
还可以通过设置过滤器对日志信息进行等级过滤
<?xml version="1.0" encoding="UTF-8" ?>
<configuration><!--<property name="" value=""></property>配置文件通用属性,通过${name}的形式取值--><property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] 日志级别:[%-5level] %c %M %L %m%n"></property>
<!-- 日志文件输出路径--><property name="logDir" value="D:/javaPro/log/logback/log"></property>
<!-- 保存的日志文件名--><property name="fileName" value="logback.log"></property><!--文件appender,默认是以追加日志的形式进行输出的--><appender name="fileAppender" class="ch.qos.logback.core.FileAppender"><!--输出文件位置--><file>${logDir}//${fileName}</file><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><property name="htmlFileName" value="logback.html"></property><property name="htmlPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}%thread%-5level%c%M%L%m"></property><!--HTML文件appender--><appender name="htmlFileAppender" class="ch.qos.logback.core.FileAppender"><!--输出文件位置--><file>${logDir}//${htmlFileName}</file><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="ch.qos.logback.classic.html.HTMLLayout"><pattern>${htmlPattern}</pattern></layout></encoder></appender><!-- 控制台Appender --><appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"><!--输出目标的配置,System.out:以黑色字体(默认)System.err:红色字体--><target>System.err</target><!-- 日志输出格式 --><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><!--可拆分归档的appender--><appender name="rollFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder><file>${logDir}/roll_logback.log</file><!--指定拆分规则--><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!--按照时间和压缩格式声明文件名,压缩格式gz--><fileNamePattern>${logDir}/roll_logback.%d{yyyy-MM-dd}.log%i.gz</fileNamePattern><!--按照文件大小进行拆分--><maxFileSize>2KB</maxFileSize></rollingPolicy></appender><!--使用过滤器,进行细粒度控制--><appender name="consoleFilterAppender" class="ch.qos.logback.core.ConsoleAppender"><target>System.err</target><!-- 日志输出格式 --><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><!--高于level中设置的级别,则打印日志--><onMatch>ACCEPT</onMatch><!--低于level中设置的级别,则屏蔽--><onMismatch>DENY</onMismatch></filter></appender><!--日志记录器配置,可以配置多个Appender,进行多方向的日志输出root => rootLoggerlevel: 表示日志级别--><root level="ALL">
<!-- <appender-ref ref="consoleAppender"/>-->
<!-- <appender-ref ref="fileAppender"/>-->
<!-- <appender-ref ref="htmlFileAppender"/>-->
<!-- <appender-ref ref="rollFileAppender"/>--><appender-ref ref="consoleFilterAppender"/></root></configuration>
启动测试:
可以看到由于过滤器中设置的是过滤出error等级及以上的信息,这里没有比error更高等级的日志信息了,所以只有error等级信息输出
异步日志
我们将日志appender进行调整回原先的打印appender,然后加入一些测试数据,观察其执行的顺序
启动测试:
可以看到无论启动多少次,下面的模拟的业务代码1=======这种代码都是在日志信息打印结束后才进行打印,这说明此时的日志是同步执行的
由此得出会出现的问题:
只要是在记录日志,那么系统本身的功能就处于一种停滞的状态当日志记录完毕后,才会执行其他的代码如果日志记录量非常庞大的话,那么我们对于系统本身业务代码的执行效率会非常低
此时可以使用logback提供的异步日志的功能
<?xml version="1.0" encoding="UTF-8" ?>
<configuration><!--<property name="" value=""></property>配置文件通用属性,通过${name}的形式取值--><property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] 日志级别:[%-5level] %c %M %L %m%n"></property>
<!-- 日志文件输出路径--><property name="logDir" value="D:/javaPro/log/logback/log"></property>
<!-- 保存的日志文件名--><property name="fileName" value="logback.log"></property><!--文件appender,默认是以追加日志的形式进行输出的--><appender name="fileAppender" class="ch.qos.logback.core.FileAppender"><!--输出文件位置--><file>${logDir}//${fileName}</file><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><property name="htmlFileName" value="logback.html"></property><property name="htmlPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}%thread%-5level%c%M%L%m"></property><!--HTML文件appender--><appender name="htmlFileAppender" class="ch.qos.logback.core.FileAppender"><!--输出文件位置--><file>${logDir}//${htmlFileName}</file><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="ch.qos.logback.classic.html.HTMLLayout"><pattern>${htmlPattern}</pattern></layout></encoder></appender><!-- 控制台Appender --><appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"><!--输出目标的配置,System.out:以黑色字体(默认)System.err:红色字体--><target>System.err</target><!-- 日志输出格式 --><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><!--可拆分归档的appender--><appender name="rollFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder><file>${logDir}/roll_logback.log</file><!--指定拆分规则--><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!--按照时间和压缩格式声明文件名,压缩格式gz--><fileNamePattern>${logDir}/roll_logback.%d{yyyy-MM-dd}.log%i.gz</fileNamePattern><!--按照文件大小进行拆分--><maxFileSize>2KB</maxFileSize></rollingPolicy></appender><!--使用过滤器,进行细粒度控制--><appender name="consoleFilterAppender" class="ch.qos.logback.core.ConsoleAppender"><target>System.err</target><!-- 日志输出格式 --><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><!--高于level中设置的级别,则打印日志--><onMatch>ACCEPT</onMatch><!--低于level中设置的级别,则屏蔽--><onMismatch>DENY</onMismatch></filter></appender><!-- 添加异步任务--><appender name="asyncAppender" class="ch.qos.logback.classic.AsyncAppender">
<!-- 指定异步任务执行的appender--><appender-ref ref="consoleAppender"/></appender><!--日志记录器配置,可以配置多个Appender,进行多方向的日志输出root => rootLoggerlevel: 表示日志级别--><root level="ALL"><appender-ref ref="asyncAppender"/>
<!-- <appender-ref ref="consoleAppender"/>-->
<!-- <appender-ref ref="fileAppender"/>-->
<!-- <appender-ref ref="htmlFileAppender"/>-->
<!-- <appender-ref ref="rollFileAppender"/>-->
<!-- <appender-ref ref="consoleFilterAppender"/>--></root></configuration>
启动测试
此时可以看到业务代码在日志信息中间就执行了,实现了异步任务的功能
自定义logger
在使用中我们还可以使用自定义的logger进行配置
启动测试
可以看到只打印了info及以上等级的日志
log4j2
简介
Apache Log4j 2 是对 Log4j 的升级,它比其前身 Log4j 1.x 提供了重大改进,并提供了Logback 中可用的许多改进,同时修复了 Logback 架构中的一些问题。被誉为是目前最优秀的Java日志框架。
特征
Log4j2包含基于LMAX Disruptor 库的下一代异步记录器。在多线程场景中,异步记录器的吞吐量比 Log4j 1.x 和 Logback 高 18 倍,延迟低。
自动重新加载配置
与Logback一样,Log4j2可以在修改时自动重新加载其配置。与 Logback 不同,它会在重新配置发生时不会丢失日志事件。。
高级过滤
与 Logback 一样,Log4j2 支持基于 Log 事件中的上下文数据,标记,正则表达式和其他组件进行过滤。
此外,过滤器还可以与记录器关联。与 Logback 不同,Log4j2 可以在任何这些情况下使用通用的 Filter类。
插件架构
Log4j使用插件模式配置组件。因此,您无需编写代码来创建和配置Appender,Layout,Pattern Converter等。在配置了的情况下,Log4j自动识别插件并使用它们。
无垃圾机制
在稳定日志记录期间,Log4j2 在独立应用程序中是无垃圾的,在 Web 应用程序中是低垃圾。这减少了垃圾收集器的压力,并且可以提供更好的响应性能。目前市面上最主流的日志门面就是 SLF4J,虽然 Log4j2 也是日志门面,因为它的日志实现功能非常强大,性能优越。所以我们一般情况下还是将 Log4j2 看作是日志的实现。SLF4j+ Log4j2 的组合,是市场上最强大的日志功能实现方式,绝对是未来的主流趋势。
案例实现
由于log4j2和前面的logback在很多方面都很相似,这里只简单演示log4j2的主要功能
引入所需依赖
<!--log4j2日志门面--><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.17.0</version></dependency><!--log4j2日志实现--><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.17.0</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version></dependency>
启动测试
日志文件拆分
<!--slf4j日志门面--><!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.32</version></dependency><!--log4j适配器,因为log4j在slf4j之前就出现了,所以需要引入一个适配器--><!-- 注意这是log4j的适配器,不是log4j2 的适配器,注意版本--><!--https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 --><!-- <dependency> --><!-- <groupId>org.slf4j</groupId> --><!-- <artifactId>slf4j-log4j12</artifactId> --><!-- <version>1.7.32</version> --><!-- </dependency> --><!--log4j2适配器,虽然log4j2自己也有门面实现,但是主流都是使用slf4j的日志门面--><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j-impl</artifactId><version>2.17.0</version><scope>test</scope></dependency><!--log4j2日志门面--><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.17.0</version></dependency><!--log4j2日志实现--><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.17.0</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version></dependency>
添加log4j2.xml文件,书写拆分日志规则
<?xml version="1.0" encoding="UTF-8" ?>
<Configuration xmlns="http://logging.apache.org/log4j/2.0/config" status="off"><Properties><Property name="logDir">D:/javaPro/log/logback/log4j2/log</Property><Property name="fileName">log4j2.log</Property><Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %m%n</Property><Property name="rollLogName">roll_log.log</Property><!--文件拆分时 存放的位置$${date:yyyy-MM-dd} : 根据日期当天,创建一个文件夹,例如:2021-12-26,记录当前的所有日志信息(拆分出来的日志放在这个文件夹中)%i:序号 从0开始--><Property name="rollFilePattern">$${date:yyyy-MM-dd}//roll_log_%d{yyyy-MM-dd-mm}_%i.log</Property></Properties><Appenders><!-- 控制台appender--><Console name="consoleAppender" target="SYSTEM_OUT"><PatternLayout pattern="${pattern}"/></Console><!-- 文件appender--><File name="fileAppender" fileName="${logDir}//${fileName}"><PatternLayout pattern="${pattern}"/></File><!--滚动文件appender
按照指定规则来扮日志文件
fileName: 日志文件的名字
filePattern: 日志文件拆分后文件的命名规则--><RollingFile name="rollingFileAppender"fileName="${logDir}//${rollLogName}"filePattern="${logDir}//${rollFilePattern}"><PatternLayout pattern="${pattern}"/><Policies><!--在系统启动时,触发拆分规则,产生一个日志文件--><OnStartupTriggeringPolicy/><!--按照文件大小拆分,当fileName属性指定的文件超过该大小时,触发拆分事件--><SizeBasedTriggeringPolicy size="10KB"/><!--按照时间节点拆分,拆分规则就是filePattern--><!--<TimeBasedTriggeringPolicy interval="1" modulate="true"/>--></Policies><!--在同一目录下,文件的个数限制30个,如果超出了设置的规则,则根据时间进行覆盖,新的覆盖旧的--><DefaultRolloverStrategy max="30" /></RollingFile></Appenders><!-- 可以配置N多个Logger,包括Root和自定义Logger--><Loggers><Root level="trace"><AppenderRef ref="consoleAppender"/><!-- <AppenderRef ref="fileAppender"/> --><AppenderRef ref="rollingFileAppender"/></Root></Loggers>
</Configuration>
模拟日志测试
SpringBoot整合
SpringBoot 是现今市场上最火爆用来简化 spring 开发的框架,springboot 日志也是开发中常用的日志系统。
SpringBoot 默认就是使用SLF4J作为日志门面,Logback作为日志实现来记录日志。
引入所需依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
整合logBack实现日志拆分
新建logback.xml文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration><property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L %thread %m%n"></property><property name="logDir" value="D:\\javaPro\\log\\logback\\log4j2\\log\\springbootLog\\logback"></property><!--控制台日志--><appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"><!--红色字体打印--><target>System.err</target><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><!--可拆分归档的文件日志--><appender name="rollFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"><!--日志输出格式--><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder><!--文件位置--><file>${logDir}//roll_logback.log</file><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!--按照时间和压缩格式声明文件名,压缩格式gz--><fileNamePattern>${logDir}//roll_logback.%d{yyyy-MM-dd}.log%i.gz</fileNamePattern><!-- 按照文件大小拆分,当日志文件达到这个大小时,将该文件以压缩格式归档 --><maxFileSize>1KB</maxFileSize></rollingPolicy></appender><!--自定义logger--><logger name="com.example" level="info" additivity="false"><appender-ref ref="consoleAppender"/><appender-ref ref="rollFileAppender"/></logger></configuration>
启动测试
查看指定文件夹下的日志文件是否拆分
整合log4j2实现日志拆分
由于log4j2性能的强大,以及当今市场上越来越多的项目选择使用slf4j+log4j2的组合,springboot默认使用的是slf4j+logback的组合,但我们可以将默认的logback置换为log4j2.
启动器的依赖,间接的依赖logback,所以需要将之前的环境中,logback的依赖去除
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><!--排除掉原始日志依赖,达到去除logback依赖的目的--><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency> <!--添加log4j2依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId></dependency>
添加log4j2.xml文件
<?xml version="1.0" encoding="UTF-8" ?><Configuration xmlns="http://logging.apache.org/log4j/2.0/config" status="off"><Properties><Property name="logDir">D:\\javaPro\\log\\logback\\log4j2\\log\\springbootLog\\log4j2</Property><Property name="rollLogName">roll_log.log</Property><Property name="rollFilePattern">$${date:yyyy-MM-dd}//roll_log_%d{yyyy-MM-dd-mm}_%i.log</Property><Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %m%n</Property></Properties><Appenders><!-- 控制台appender--><Console name="consoleAppender" target="SYSTEM_ERR"><PatternLayout pattern="${pattern}"/></Console><RollingFile name="rollingFileAppender"fileName="${logDir}//${rollLogName}"filePattern="${logDir}//${rollFilePattern}"><PatternLayout pattern="${pattern}"/><Policies><OnStartupTriggeringPolicy/><SizeBasedTriggeringPolicy size="10KB"/><!--<TimeBasedTriggeringPolicy interval="1" modulate="true"/>--></Policies><DefaultRolloverStrategy max="30" /></RollingFile></Appenders><Loggers><Root level="info"><AppenderRef ref="consoleAppender"/><AppenderRef ref="rollingFileAppender"/></Root></Loggers>
</Configuration>
启动测试
源码地址
日志源码