目录
1.⽇志概述
1.1 ⽇志是⽤来做什么的?
1.2 为什么要⽤到⽇志框架?
1.3 现有的⽇志框架有哪些?
1.4 ⽇志⻔⾯技术
2.logback
2.1 logback介绍
2.1.1 logback 模块
2.1.2 logback 组件
2.1.3 logback 配置
2.1.4 logback.xml 配置⽂件解析
2.2 SLF4j+logback进⾏⽇志管理
2.2.2 配置⽂件
2.2.3 代码实现
2.2.6 异步⽇志
2.2.7 ⾃定义Logger
2.2.8 配置⽂件转换器
2.2.9 logback-access模块
3.Log4j2
3.1.1Log4j2介绍
3.2.1 XML配置⽂件解析
3.2.2 Log4j2的使⽤
3.2.3 Log4j的Bug及解决⽅案
4.SpringBoot⽇志管理
4.1 SpringBoot⾃定义⽇志
4.1.1 SpringBoot默认的⽇志配置
4.1.2 使⽤logback-spring.xml⾃定义配置
4.1.3 多环境输出⽇志⽂件
4.2 SpringBoot整合Log4j2
5.demo源码:Java日志模板: Java日志信息,包括slf42,logback,springboot整合slf42
1.⽇志概述
1.1 ⽇志是⽤来做什么的?
⽇志⽂件是⽤于记录系统操作事件的⽂件集合,可分为
事件⽇志
和
消息⽇志
。具
有处理历史数据、诊断问题的追踪以及理解系统的活动等重要作⽤。
1.2 为什么要⽤到⽇志框架?
因为软件系统发展到今天已经很复杂了,特别是服务器端软件,涉及到的知识,内
容,问题太多。在某些⽅⾯使⽤别⼈成熟的框架,就相当于让别⼈帮你完成⼀些基
础⼯作,你只需要集中精⼒完成系统的业务逻辑设计。⽽且框架⼀般是成熟,稳健
的,它可以处理系统很多细节问题,⽐如,事务处理,安全性,数据流控制等问
题。还有框架⼀般都经过很多⼈使⽤,所以结构很好,所以扩展性也很好,⽽且它
是不断升级的,你可以直接享受别⼈升级代码带来的好处。
1.3 现有的⽇志框架有哪些?
- JUL(java util logging)
- logback
- log4j
- log4j2
- JCL(Jakarta Commons Logging)
- slf4j( Simple Logging Facade for Java)
⽇志框架出现的历史顺序:
log4j -->JUL-->JCL--> slf4j --> logback --> log4j2
1.4 ⽇志⻔⾯技术
当我们的系统变的更加复杂的时候,我们的⽇志就容易发⽣混乱。随着系统开发的 进⾏,可能会更新不同的⽇志框架,造成当前系统中存在不同的⽇志依赖,让我们 难以统⼀的管理和控制。就算我们强制要求所有的模块使⽤相同的⽇志框架,系统 中也难以避免使⽤其它类似spring
mybatis
等其它的第三⽅框架,它们依赖于我们规定不同的⽇志框架,⽽且它们⾃身的⽇志系统就有着不⼀致性,依然会出现⽇志体系的混乱。 所以我们需要借鉴JDBC的思想,为⽇志系统也提供⼀套⾯,那么我们就可以⾯ 向这些接⼝规范来开发,避免了直接依赖具体的⽇志框架。这样我们的系统在⽇志中,就存在了⽇志的⻔⾯和⽇志的实现。
1.4.1
⽇志⻔⾯技术的优点
1.
⾯向接⼝开发,不再依赖具体的实现类。减少代码的耦合
2.
项⽬通过导⼊不同的⽇志实现类,可以灵活的切换⽇志框架
3.
统⼀
API
,⽅便开发者学习和使⽤
4.
统⼀配置便于项⽬⽇志的管理
1.4.2
⽇志⻔⾯和⽇志实现的关系
⽤户可以使⽤⽇志⻔⾯,然后根据需求,动态的选择具体的⽇志实现框架。这样就
可以使所有⽇志实现框架拥有统⼀的规范。
2.logback
2.1 logback介绍
官⽹:
http://logback.qos.ch
Logback
是由
log4j
创始⼈设计的另⼀个开源⽇志组件,性能⽐
log4j
要好。
log4j,
logback, slf4j
都出⾃于他之⼿。
SLF4j
绑定
Logback
⽆缝衔接,只需要⼀个
logback-classic-1.0.13.jar
,这个绑定包不
是
slf4j
项⽬提供的,⽽是是
logback
项⽬提供的,它本身就是基于
slf4j API
实现的。
logback
拥有以下优点:
- 内核重写、测试充分、初始化内存加载更⼩,这⼀切让logback性能和log4j相⽐有诸多倍的提升
- logback⾮常⾃然地直接实现了slf4j,这个严格来说算不上优点,只是这样,再理解slf4j的前提下会很容易理解logback,也同时很容易⽤其他⽇志框架替换 logback
- logback有⽐较⻬全的200多⻚的⽂档
- logback当配置⽂件修改了,⽀持⾃动重新加载配置⽂件,扫描过程快且安全, 它并不需要另外创建⼀个扫描线程
- ⽀持⾃动去除旧的⽇志⽂件,可以控制已经产⽣⽇志⽂件的最⼤数量
2.1.1 logback 模块
logback-core:
其他两个模块的基础模块
logback-class
:它是
log4j
的改良版本,完整实现了
Slf4j API
logback-access:
访问模块与
servlet
容器继承提供通过
Http
来访问⽇志的功能
2.1.2 logback 组件
1
)
Logger:
⽇志的记录器,把它关联到应⽤的对应的
context
上后,主要⽤于存放⽇志对象,也可以定义⽇志类型、级别。
2
)
Appender:
⽤于指定⽇志输出的⽬的地,可以是控制台、⽂件、数据库等等。
3
)
Layout:
负责把事件转换成字符串,格式化的⽇志信息的输出。在
logback
中Layout对象被封装在
encoder
中。
2.1.3 logback 配置
logback
会依次读取以下类型配置⽂件
:
1
)
logback.grovy
2
)
logback-test.xml
3
)
logback.xml
2.1.4 logback.xml 配置⽂件解析
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!-- 定义配置属性,可以直接使用该属性的值,格式:${name} -->
<property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n"/>
<property name="log_dir" value="G://logs"/>
<!-- 控制台日志输出的Appender -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<target>System.out</target> <!--System.err 区别就是颜色不同-->
<!--日志消息格式设置 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
</appender>
<!-- 输出文件Appender -->
<appender name="file" class="ch.qos.logback.core.FileAppender">
<file>${log_dir}/logback.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
</appender>
<!-- html格式日志文件输出Appender -->
<appender name="html" class="ch.qos.logback.core.FileAppender">
<file>${log_dir}/logback.html</file>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.classic.html.HTMLLayout">
<pattern>%-5level%d{yyyy-MM-dd HH:mm:ss.SSS}%c %M %L %thread %m</pattern>
</layout>
</encoder>
</appender>
<!-- 日志拆分和归档压缩的Appender -->
<appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志文件保存的路径 -->
<file>${log_dir}/roll_logback.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
<!-- 拆分规则 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 按照时间和压缩格式声明拆分的文件名 -->
<fileNamePattern>${log_dir}/rolling.%d{yyyy-MM-dd-HH-ss}.log%i.gz</fileNamePattern>
<maxFileSize>1MB</maxFileSize>
</rollingPolicy>
</appender>
<!-- 日志级别过滤器 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<omMismatch>DENY</omMismatch>
</filter>
<!-- 异步日志 -->
<appender name="asyncInfo" class="ch.qos.logback.classic.AsyncAppender">
<!-- 默认不丢失日志,如果队列的80%已满,则会丢失TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 默认256 队列大小 -->
<queueSize>256</queueSize>
<!-- 绑定异步的appender只能添加一个 -->
<appender-ref ref="rollFile"/>
</appender>
<root level="ALL">
<appender-ref ref="console"/>
<appender-ref ref="rollFile"/>
<appender-ref ref="file"/>
<appender-ref ref="html"/>
</root>
</configuration>
⽇志输出格式:
%-5level
%d{yyyy-MM-dd HH:mm:ss.SSS}⽇期
%c类的完整名称
%M为method
%L为⾏号
%thread线程名称
%m或者%msg为信息
%n换⾏
格式化输出:
%d表示⽇期,
%thread表示线程名,
%-5level:级别从左显示5个字符宽度
%msg:⽇志消息
%n是换⾏符
2.2 SLF4j+logback进⾏⽇志管理
SLF4j
绑定
Logback
,只需要⼀个
logback-classic-1.0.13.jar
2.2.1
导包
<dependencies>
<!-- slf4j ⽇志⻔⾯ -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<!-- logback ⽇志实现 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
2.2.2 配置⽂件
log4j2.xml
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!-- 定义配置属性,可以直接使用该属性的值,格式:${name} -->
<property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n"/>
<property name="log_dir" value="G://logs"/>
<!-- 控制台日志输出的Appender -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<target>System.out</target> <!--System.err 区别就是颜色不同-->
<!--日志消息格式设置 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
</appender>
<!-- 输出文件Appender -->
<appender name="file" class="ch.qos.logback.core.FileAppender">
<file>${log_dir}/logback.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
</appender>
<!-- html格式日志文件输出Appender -->
<appender name="html" class="ch.qos.logback.core.FileAppender">
<file>${log_dir}/logback.html</file>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.classic.html.HTMLLayout">
<pattern>%-5level%d{yyyy-MM-dd HH:mm:ss.SSS}%c %M %L %thread %m</pattern>
</layout>
</encoder>
</appender>
<!-- 日志拆分和归档压缩的Appender -->
<appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志文件保存的路径 -->
<file>${log_dir}/roll_logback.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
<!-- 拆分规则 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 按照时间和压缩格式声明拆分的文件名 -->
<fileNamePattern>${log_dir}/rolling.%d{yyyy-MM-dd-HH-ss}.log%i.gz</fileNamePattern>
<maxFileSize>1MB</maxFileSize>
</rollingPolicy>
</appender>
<!-- 日志级别过滤器 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<omMismatch>DENY</omMismatch>
</filter>
<!-- 异步日志 -->
<appender name="asyncInfo" class="ch.qos.logback.classic.AsyncAppender">
<!-- 默认不丢失日志,如果队列的80%已满,则会丢失TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 默认256 队列大小 -->
<queueSize>256</queueSize>
<!-- 绑定异步的appender只能添加一个 -->
<appender-ref ref="rollFile"/>
</appender>
<root level="ALL">
<appender-ref ref="console"/>
<appender-ref ref="rollFile"/>
<appender-ref ref="file"/>
<appender-ref ref="html"/>
</root>
</configuration>
2.2.3 代码实现
package com.wang;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.stream.IntStream;
/**
* @author 飞
*/
public class Test {
public static final Logger LOGGER = LoggerFactory.getLogger(Test.class);
public static void main(String[] args) {
IntStream.range(0, 10000).forEach(i -> {
LOGGER.trace("trace");
LOGGER.debug("debug"); // 默认输出级别
LOGGER.info("info");
LOGGER.warn("warn");
LOGGER.error("error");
});
}
}
2.2.4
⽇志拆分
所有信息都输出到同⼀个⽇志⽂件,⽇志的产⽣速度很快,⽂件⼀⼤,就很难分析,因此需要进⾏拆分。
<!-- 日志拆分和归档压缩的Appender -->
<appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志文件保存的路径 -->
<file>${log_dir}/roll_logback.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
<!-- 拆分规则 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 按照时间和压缩格式声明拆分的文件名 -->
<fileNamePattern>${log_dir}/rolling.%d{yyyy-MM-dd-HH-ss}.log%i.gz</fileNamePattern>
<maxFileSize>1MB</maxFileSize>
</rollingPolicy>
</appender>
2.2.5
过滤器
<!-- 日志级别过滤器 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<omMismatch>DENY</omMismatch>
</filter>
该过滤器表示:⼤于等于
error
级别的⽇志才会被输出到⽂件中
2.2.6 异步⽇志
为了提升性能,应该将⽇志设置为异步,同步⽇志意味着⽇志必须完成才能执⾏后续代码,但是⽇志毕竟是 io
操作,会影响程序速度配置异步⽇志很简单,新增⼀个 appender
,指定其为
async,
并调⽤现有的
appender
即可。
<!-- 异步日志 -->
<appender name="asyncInfo" class="ch.qos.logback.classic.AsyncAppender">
<!-- 默认不丢失日志,如果队列的80%已满,则会丢失TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 默认256 队列大小 -->
<queueSize>256</queueSize>
<!-- 绑定异步的appender只能添加一个 -->
<appender-ref ref="rollFile"/>
</appender>
2.2.7 ⾃定义Logger
我们可以针对⾃⼰的业务代码⾃定义
logger
对象,可以不必继承
rootLogger
。
<!--⾃定义logger对象 additivity属性表示⾃定义logger对象是否继承rootLogger
在 com.wang包下的类⽇志都使⽤此logger对象-->
<logger name="com.wang" level="info" additivity="false">
<appender-ref ref="console" />
</logger>
2.2.8 配置⽂件转换器
http://logback.qos.ch/translator/
可以将
log4j
的配置转成
logback
的配置格式
2.2.9 logback-access模块
logback-access
模块与
Servlet
容器
(
如
Tomcat
和
Jetty)
集成,以提供
HTTP
访问⽇志功能。我们可以使⽤logback-access
模块来替换
tomcat
的访问⽇志。
具体参考官⽹⽂档
https://logback.qos.ch/access.h
3.Log4j2
3.1.1Log4j2介绍
Log4j2
是对
Log4j
的升级版本,
015
年
5
⽉,
Apache
宣布
log4j1.x
停⽌更新。
Log4j
与
Log4j2
下载地址:
https://logging.apache.org/
log4j2
参考了
logback
的⼀些优秀的设计,并且修复了⼀些问题,因此带来了⼀些重⼤的提升,主要有:
1
、异常处理:在
logback
中,
Appender
中的异常不会被应⽤感知到,但是在
log4j2中,提供了⼀些异常处理机制。
2
、性能提升:
log4j2
相较于
log4j 1
和
logback
都具有很明显的性能提升。
3
、⾃动重载配置:参考了
logback
的设计,提供⾃动刷新参数配置,可以动态的修改⽇志的级别⽽不需要重启应⽤。
4
、⽆垃圾机制,
log4j2
在⼤部分情况下,都可以使⽤其设计的⼀套⽆垃圾机制,避免频繁的⽇志收集导致的jvm gc
。
log4j 2.x
版本不再⽀持像
1.x
中的
.properties
后缀的⽂件配置⽅式,
2.x
版本配置⽂件
后缀名只能为
".xml",".json"
或者
".jsn"
。
log4j2
虽然采⽤
xml
⻛格进⾏配置,依然包含三个组件分别是
Loggers
(记录器)、
Appender
(输出⽬的地)、
Layout
(⽇志布局)。
配置⽂件的位置:
log4j2
默认会在
classpath
⽬录下寻找
log4j2.xml
、
log4j.json
、log4j.jsn等名称的⽂件。
3.2.1 XML配置⽂件解析
1
、根节点
Configuration
有两个属性
:status
和
monitorinterval,
有两个⼦节点:Appenders
和
Loggers(
表明可以定义多个
Appender
和
Logger
status ⽤来指定 log4j 本身的打印⽇志的级别monitorinterval 为 log4j 2.x 新特点⾃动重载配置。指定⾃动重新配置的监测间隔时间,单位是 s, 最⼩是 5s
2
、
Appenders
节点,常⻅的有三种⼦节点
:Console
、
File
、
RollingFile
Console 节点⽤来定义输出到控制台的 AppenderFile 节点⽤来定义输出到指定位置的⽂件的 AppenderRollingFile 节点⽤来定义超过指定⼤⼩⾃动删除旧的创建新的的 Appender
通过在⼦节点中加⼊进⾏⽇志布局:%p : 输出⽇志信息优先级,即 DEBUG , INFO , WARN , ERROR , FATAL,%d : 输出⽇志时间点的⽇期或时间,默认格式为 ISO8601 ,也可以在其后指定格式,⽐如:%d{yyy MMM dd HH : mm : ss,SSS} ,输出类似: 2002 年 10 ⽉ 18 ⽇ 22 : 10 : 28 ,921%r : 输出⾃应⽤启动到输出该 log 信息耗费的毫秒数%c : 输出⽇志信息所属的类⽬,通常就是所在类的全名%t : 输出产⽣该⽇志事件的线程名%l : 输出⽇志事件的发⽣位置,相当于 %C.%M(%F : %L) 的组合 , 包括类⽬名、发⽣的线程,以及在代码中的⾏数。举例: Testlog4.main(TestLog4.Java : 10)%x : 输出和当前线程相关联的 NDC( 嵌套诊断环境 ), 尤其⽤到像 Java servlets 这样的多客户多线程的应⽤中。%% : 输出⼀个 ”%” 字符%F : 输出⽇志消息产⽣时所在的⽂件名称%L : 输出代码中的⾏号%m : 输出代码中指定的消息 , 产⽣的⽇志具体信息%n : 输出⼀个回⻋换⾏符, Windows 平台为 ”\r\n” , Unix 平台为 ”\n” 输出⽇志信息换⾏
3
、
Loggers
节点,常⻅的有两种:
Root
和
Logger
Root 节点⽤来指定项⽬的根⽇志,如果没有单独指定 Logger ,那么就会默认使⽤该Root⽇志输出Logger 节点⽤来单独指定⽇志的形式,⽐如要为指定包下的 class 指定不同的⽇志级别等。
3.2.2 Log4j2的使⽤
1
导包
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId> <!-- ⽇志⻔⾯ -->
<version>2.19</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId><!-- ⽇志实现 -->
<version>2.19</version>
</dependency>
2
创建配置⽂件
<?xml version="1.0" encoding="UTF-8" ?>
<configuration status="error">
<!--定义所有的appender -->
<appenders>
<Console name="console" target="SYSTEM_OUT">
<!--控制台日志级别为trace以上的信息(ACCEPT) 其他的直接拒绝(onMismatch)-->
<ThresholdFilter level = "trace" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern = "%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %m%n"/>
</Console>
<File name="log" fileName="G:/logs/log4j2.log" append = "true">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %m%n"/>
</File>
<File name="error" fileName="G:/logs/log4j2_error.log">
<ThresholdFilter level = "error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern = "%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %m%n"/>
</File>
<!--打印出所有消息,每次大小超过size,则size大小的日志会自定存入按年份-月份建立的文件夹下面并进行压缩,作为存档 -->
<RollingFile name="rollingFile" fileName="G:/logs/web.log"
filePattern="logs/$${date:yyyy-MM}/web-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern = "%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %m%n"/>
<SizeBasedTriggeringPolicy size="2MB"/>
</RollingFile>
</appenders>
<loggers>
<root level = "trace">
<appender-ref ref="rollingFile"/>
<appender-ref ref="console"/>
<appender-ref ref="error"/>
<appender-ref ref="log"/>
</root>
</loggers>
</configuration>
3
应⽤
package com.wang;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Test {
private static Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
public static void main(String[] args) {
for (int i= 0;i<3;i++){
// 记录trace级别的日志信息
logger.trace("log4j日志输出:This is trace message.");
// 记录debug级别的日志信息
logger.debug("log4j日志输出:This is debug message.");
// 记录info级别的日志信息
logger.info("log4j日志输出:This is info message.");
// 记录error级别的日志信息
logger.error("log4j日志输出:This is error message.");
}
}
}
3.2.3 Log4j的Bug及解决⽅案
解决⽅式
- 禁⽤lookup或JNDI服务
罪魁祸⾸就是lookup
和
JNDI
,那么直接修改配置⽂件 log4j2.formatMsgNoLookups=True或禁⽤
JNDI
服务,不过⼀般产⽣问题的服务都是线上已经在跑的服务,禁⽤的时候要注意评估⼀下是否允许。
- 升级Apache Log4j
这次产⽣的影响范围主要是在
Apache Log4j 2.x <= 2.14.1
,所以直接把
Log4j
升级即可解决。
4.SpringBoot⽇志管理
4.1 SpringBoot⾃定义⽇志
SpringBoot
内部使⽤
logback
作为系统⽇志实现的框架,将⽇志输出到控制台,不会写到⽇志⽂件。如果在application.properties
或
application.yml
配置,这样只能配置简单的场景,保存路径、⽇志格式等。复杂的场景(区分 info
和
error
的⽇志、每天产⽣⼀个⽇志⽂件等)满⾜不了,只能⾃定义配置⽂件logback-spring.xml
。
4.1.1 SpringBoot默认的⽇志配置
格式说明时间戳 , 精确到毫秒 : 2022-10-27 12:38:39.195logback ⽇志级别 . ⽇志级别分为: TRACE 、 DEBUG 、 INFO 、 WARN 、 ERROR 、FATAL: INFO进程 ID: 16816分割符 : 默认是 : ---线程名称 : [main]
SpringBoot
从控制台打印出来的⽇志级别默认只有
INFO
及以上级别,可以在application.properties中修改⽇志级别
logging.level.root=WARN
。
在
application.properties
配置⽂件中添加:
logging.level.root = WARN
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
package com.wang.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.stream.IntStream;
/**
* @author 飞
*/
@Slf4j //lombok 提供的注解
@RestController
@RequestMapping("log")
public class LogController {
//如果不使⽤lombok就需要⽤以下代码获取⽇志操作对象
//Logger log = LoggerFactory.getLogger(LogController.class);
@GetMapping("/test")
public String test(){
IntStream.range(0, 1000).forEach(i -> {
log.trace("hello trace");
log.debug("hello debug");
log.info("hello info");
log.warn("hello warn");
});
return "SpringBoot日志管理";
}
}
root
是项⽬所有的⽇志级别。启动成功了,但是没有⽇志输出。我们把默认的⽇志级别设置成WARN,
按照层级关系
INFO,DEBUG,TRACE
的⽇志都不输出。我们在 application.properties
将
root
的⽇志级别改成
INFO
,⾃⼰的写的业务包⽇志级别改成DEBUG
。
logging.level.root=INFO //root⽇志以INFO级别输出信息
logging.level.com.wang.controller.config=WARN //指定config包下的类以WARN级别输出
运⾏之后,
log.info("
这是
info
级别⽇志
")
没有输出。
⽇志的其它配置项logging.config ⽇志配置;logging.logback.rollingpolicy.max-file-size ( 低版本⽤ logging.file.max-size ) 最⼤⽇志⽂件⼤⼩;logging.logback.rollingpolicy.max-history ( 低版本 logging.file.max-history ) 最⼤归档⽂件数量;logging.pattern.console 控制台输出的⽇志模式;logging.pattern.dateformat ⽇志的⽇期格式;logging.pattern.file 默认使⽤⽇志模式logging.pattern.level ⽇志级别logging.config ⽇志配置;logging.logback.rollingpolicy.max-file-size ( 低版本⽤ logging.file.max-size ) 最⼤⽇志⽂件⼤⼩;logging.logback.rollingpolicy.max-history ( 低版本 logging.file.max-history ) 最⼤归档⽂件数量;logging.pattern.console 控制台输出的⽇志模式;logging.pattern.dateformat ⽇志的⽇期格式;logging.pattern.file 默认使⽤⽇志模式logging.pattern.level ⽇志级别
4.1.2 使⽤logback-spring.xml⾃定义配置
⽇志服务⼀般都在
ApplicationContext
创建前就初始化了,它并不是必须通过
Spring的配置⽂件控制。因此通过系统属性和传统的Spring Boot
外部配置⽂件依然可以很好的⽀持⽇志控制和管理。在类路径下放置⾃定义⽇志配置xml
⽂件,
SpringBoot就不会使⽤它本身的默认⽇志配置了。下图是SpringBoot
官⽅⽂档的提示内容,意思是:根据您的⽇志记录系统,将加载相应的⽂件使⽤。即如果我们使⽤logback
⽇志框架,那么可以使⽤
logback-spring.xml、
logback-spring.groovy
、
logback.xml
、
logback.groovy
之⼀作为配置⽂件来加载。根据不同的⽇志系统,你可以按如下规则组织配置⽂件名,并且放在src/main/resources下⾯就能被正确加载:
Logback:logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovy
Log4j:log4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xml
Log4j2:log4j2-spring.xml, log4j2.xml
JDK (Java Util Logging):logging.properties
logback-spring.xml
的配置模板:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!-- 定义配置属性,可以直接使⽤该属性的值,格式:${name} -->
<property name="pattern" value="[%-5level] %d{yyyy-MM-dd
HH:mm:ss.SSS} %c %M %L [%thread] %m%n"/>
<property name="log_dir" value="C://logs"/>
<!-- 控制台⽇志输出的Appender -->
<appender name="console"
class="ch.qos.logback.core.ConsoleAppender">
<target>System.out</target> <!--System.err 区别就是颜⾊不
同-->
<!--⽇志消息格式设置 -->
<encoder
class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
</appender>
<!-- 输出⽂件Appender -->
<appender name="file"
class="ch.qos.logback.core.FileAppender">
<file>${log_dir}/logback.log</file>
<encoder
class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
</appender>
<!-- html格式⽇志⽂件输出Appender -->
<appender name="html"
class="ch.qos.logback.core.FileAppender">
<file>${log_dir}/logback.html</file>
<encoder
class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout
class="ch.qos.logback.classic.html.HTMLLayout">
<pattern>%-5level%d{yyyy-MM-dd HH:mm:ss.SSS}%c %M
%L %thread %m</pattern>
</layout>
</encoder>
</appender>
<!-- ⽇志拆分和归档压缩的Appender -->
<appender name="rollFile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- ⽇志⽂件保存的路径 -->
<file>${log_dir}/roll_logback.log</file>
<encoder
class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
<!-- 拆分规则 -->
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 按照时间和压缩格式声明拆分的⽂件名 -->
<fileNamePattern>${log_dir}/rolling.%d{yyyy-MM-dd-HHss}.log%i.gz</fileNamePattern>
<maxFileSize>1MB</maxFileSize>
</rollingPolicy>
</appender>
<!-- ⽇志级别过滤器 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<omMismatch>DENY</omMismatch>
</filter>
<!-- 异步⽇志 -->
<appender name="asyncInfo"
class="ch.qos.logback.classic.AsyncAppender">
<!-- 默认不丢失⽇志,如果队列的80%已满,则会丢失TRACT、DEBUG、
INFO级别的⽇志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 默认256 队列⼤⼩ -->
<queueSize>256</queueSize>
<!-- 绑定异步的appender只能添加⼀个 -->
<appender-ref ref="rollFile"/>
</appender>
<root level="ALL">
<appender-ref ref="console"/>
<appender-ref ref="rollFile"/>
<appender-ref ref="asyncInfo"/>
<!-- <appender-ref ref="file"/>-->
<!-- <appender-ref ref="html"/>-->
</root>
</configuration>
4.1.3 多环境输出⽇志⽂件
SpringBoot
官⽅建议使⽤
logback-spring.xml
作为
logback
框架的⾃定义⽇志配置⽂件,使⽤logback-spring.xml
⽽不是
logback.xml
,因为带
-spring
后缀的配置⽂件可以使⽤使⽤Spring
扩展
profile
⽀持,提供
profile
多环境⽇志输出得功能。
Logback
配置⽂件中的 节点指令允许您根据配置⽂件激活参数
(active)
选择性的包含和排查部分配置信息。根据不同环境来定义不同的⽇志输出,在 logback-spring.xml中使⽤ 节点来定义,⽅法如下:
<!--开发环境:打印控制台-->
<springProfile name="dev">
<!--⽤来设置某⼀个包或者具体的某⼀个类的⽇志打印级别,可以让控制台输出debug addtivity="false"不向上传递-->
<logger name="com.laoxue.contoller.test" level="debug"
addtivity="false"/>
<!--root节点是必选节点,⽤来指定最基础的⽇志输出级别,只有⼀个level属性,可以包含零个或多个appender元素-->
<root level="INFO">
<appender-ref ref="console" />
</root>
</springProfile>
<!--⽣产环境:输出到⽂件-->
<springProfile name="pro">
<root level="INFO">
<appender-ref ref="rollFile"/>
<appender-ref ref="asyncInfo"/>
</root>
</springProfile>
以启动服务的时候指定
profile
(如不指定使⽤默认),如指定
prod
的⽅式为:
java -jar xxx.jar –spring.profiles.active=prod
4.2 SpringBoot整合Log4j2
Apache Log4j 2
是
Log4j1. x
的升级版,⽐它的祖先
Log4j
有了很⼤的改进,和 logback对⽐有很⼤的改进。除了内部设计的调整外,主要有以下⼏点的⼤升级:
- 更简化的配置
- 更强⼤的参数格式化
- 强⼤的异步性能
Log4j 2
中,分为
API(log4j-api
)和实现
(log4j-core)
两个模块。
API
和
slf4j
是⼀个类
型,属于⽇志抽象
/
⻔⾯,⽽实现部分,才是
Log4j 2
的核⼼。
- org.apache.logging.log4j » log4j-api
- org.apache.logging.log4j » log4j-core
相⽐与其他的⽇志系统,
log4j2
丢数据这种情况少;
disruptor
技术,在多线程环境下,性能⾼于logback
等
10
倍以上;利⽤
jdk1.5
并发的特性,减少了死锁的发⽣;同步⽇志模式下, Logback
的性能是最糟糕的,
log4j2
的性能⽆论在同步⽇志模式还是异步⽇志模式下都是最佳的。
1.pom配置
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- 去掉springboot默认配置 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
<version>2.7.5</version>
</dependency>
<!-- 引入log4j2的配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
</dependencies>
2. 配置⽂件
默认名
log4j2-spring.xml.
如果是其它的名字需要在配置⽂件中指定
logging.config=xxx.xml
配置⽂件模板:
<?xml version="1.0" encoding="UTF-8"?>
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration monitorInterval="5">
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--变量配置-->
<Properties>
<!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
<!-- %logger{36} 表示 Logger 名字最长36个字符 -->
<property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
<!-- 定义日志存储的路径 -->
<property name="FILE_PATH" value="G://logs" />
<property name="FILE_NAME" value="springboot-log" />
</Properties>
<appenders>
<console name="Console" target="SYSTEM_OUT">
<!--输出日志的格式-->
<PatternLayout pattern="${LOG_PATTERN}"/>
<!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
</console>
<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用-->
<File name="File-log" fileName="${FILE_PATH}/test.log" append="false">
<PatternLayout pattern="${LOG_PATTERN}"/>
</File>
<!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/${FILE_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="1MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<!-- 这个会打印出所有的warn及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log" filePattern="${FILE_PATH}/${FILE_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="1MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log" filePattern="${FILE_PATH}/${FILE_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="1MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
</appenders>
<!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
<!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
<logger name="org.mybatis" level="info" additivity="false">
<AppenderRef ref="Console"/>
</logger>
<!--监控系统信息-->
<!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。-->
<Logger name="org.springframework" level="info" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<root level="info"> <!--定义日志级别,大于等于info级别的日志都将被输出-->
<appender-ref ref="Console"/>
<appender-ref ref="File-log"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</loggers>
</configuration>