日志输出 logback 使用
概览
Logback 主要由三个模块组成
-
logback-core
是其它模块的基础设施,其它模块基于它构建,显然,
logback-core
提供了一些关键的通用机制 -
logback-classic
地位和作用等同于
Log4J
,它也被认为是Log4J
的一个改进版,并且它实现了简单日志门面SLF4J
-
logback-access
主要作为一个与
Servlet
容器交互的模块,比如说tomcat
或者jetty
,提供一些与HTTP
访问相关的功能
快速入门
pom.xml
引入依赖: slf4j-api,logback-core,logback-classic。其中 slf4j-api 并不是 Logback 的一部分,是另外一个项目,但是强烈建议将 slf4j 与 Logback 结合使用
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.0.11</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.11</version>
</dependency>
Demo:
package com.test.wsl.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Demo {
private static final Logger logger = LoggerFactory.getLogger(Demo.class);
public static void main(String[] args) {
logger.info("Hello world");
}
}
这里并没有引用任何一个跟
Logback
相关的类,而是引用了SLF4J
相关的类,这样在需要将日志框架切换为其它日志框架时,无需改动代码。LoggerFactory
的getLogger()
方法接收一个参数,以这个参数决定logger
的名字,这里传入了Demo
这个类的Class
实例,那么logger
的名字便是Demo
这个类的全限定类名:com.test.wsl.logback.Demo
基础
重要API
logback 里,最重要的三个类
-
Logger
位于 logback-classic 模块中, Logger 会依赖于 Appender 和 Layout 的协助,日志信息才能被正常打印出来
-
Appender
位于 logback-core 中
-
Layout
位于 logback-core 中
分层命名规则
每个
logger
都有一个name
格式与Java
语言中的包名格式相同,能够组成一个树状的结构每个
logger
都被绑定到一个logger
上下文中直接把一个
class
对象传进LoggerFactory.getLogger()
方法作为参数的原因是为了分层
例如, 命名为
com.wsl
的logger
,是命名为com.wsl.test
的logger
的父亲,是命名为com.wsl.test.logback
的logger
的祖先。
在
logger
上下文中,有一个root logger
,作为所有logger
的祖先,这是logback
内部维护的一个logger
,并非开发者自定义的logger
// 可通过以下方式获得这个 logger
Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
// ROOT
// 同样,通过 logger 的 name,就能获得对应的其它 logger 实例
Logger rootLogger = LoggerFactory.getLogger(FormAcceptanceCertificateController.class);
// com.ssjf.activiti.actest.controller.FormAcceptanceCertificateController
日志打印级别
日志级别优先级: TRACE < DEBUG < INFO < WARN < ERROR
打印规则: 指定某个level级别, 该级别及以上级别都会打印
日志级别的缺省继承:某个
logger
打印级别是可选的,可以指定打印级别也可以不指定。未指定,那么它将继承离他最近的一个有指定打印级别的祖先的打印级别。
如果
logger
先找它的父亲,而它的父亲没有指定打印级别,那么它会立即忽略它的父亲,往上继续寻找它爷爷,直到它找到root logger
。要使用
logback
, 必须为root logger
指定日志打印级别。
Appender 和 Layout
Appender
Appender
决定日志打印的目的地console/文件/网络流中
一个
logger
可以绑定多个Appender
logger 打印一条信息->自己Appender->父亲和父亲以上的祖先的 Appender(如果设置:additivity = false 不向上传递)
Layout
代表日志打印格式
如
PatternLayout
能够识别以下这条格式(详情参考logback
日志pattern
的每个参数的含义):
%-4relative [%thread] %-5level %logger{32} - %msg%n
参数化打印日志
// 这样的方式,避免了字符串拼接,也避免了多一次日志级别的判断
logger.debug("the message {} is from {}", msg, somebody);
logback 内部运行流程
- 获得过滤器链条
- 检查日志级别以决定是否继续打印
- 创建一个
LoggingEvent
对象 - 调用
Appenders
- 进行日志信息格式化
- 发送
LoggingEvent
到对应的目的地
logback 配置
配置方式
- 编程式配置
- xml 格式
- groovy 格式
logback 在启动时,根以下步骤寻找配置文件:
- 在
classpath
中寻找logback-test.xml
文件- 如果找不到
logback-test.xml
,则在classpath
中寻找logback.groovy
文件- 如果找不到
logback.groovy
,则在classpath
中寻找logback.xml
文件- 如果上述的文件都找不到,则
logback
会使用JDK
的SPI
机制查找META-INF/services/ch.qos.logback.classic.spi.Configurator
中的logback
配置实现类,这个实现类必须实现Configuration
接口,使用它的实现来进行配置- 如果上述操作都不成功,
logback
就会使用它自带的BasicConfigurator
来配置,并将日志输出到console
默认的配置
前面有提到默认的配置,由
BasicConfiguator
类配置而成,这个类的配置可以用如下的配置文件来表示
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
启动时打印状态信息
如果 logback 在启动时,解析配置文件时,出现了需要警告的信息或者错误信息,那 logback 会自动先打印出自身的状态信息。
如果希望正常情况下也打印出状态信息,则可以在代码里显式地调用使其输出
public static void main(String[] args) {
// assume SLF4J is bound to logback in the current environment
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
// print logback's internal status
StatusPrinter.print(lc);
...
}
也可以在配置文件中,指定configuration
的 debug
属性为 true
<configuration debug="true">
... the rest of the configuration file
</configuration>
还可以指定一个 Listener:
<configuration>
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
... the rest of the configuration file
</configuration>
重置默认的配置文件位置
设置 logback.configurationFile 系统变量,可以通过
-D
参数设置,所指定的文件名必须以.xml
或者.groovy
作为文件后缀,否则logback
会忽略这些文件。
输出异常栈时 jar 包信息
这个属性默认是关闭,可通过以下方式开启
<configuration packagingData="true">
...
</configuration>
也可以通过 LoggerContext
的setPackagingDataEnabled(boolean)
方法来开启
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
lc.setPackagingDataEnabled(true);
配置文件格式
基本格式: configuration
节点下配置appender
、logger
、root
根节点是 configuration
,可包含0个或多个 appender
,0个或多个 logger
,最多一个 root
。
配置 logger 节点
标签下只有一种元素,那就是 ,可以有0个或多个 Appender
属性
-
name 必要
-
level 取值可以是
TRACE, DEBUG, INFO, WARN, ERROR, ALL, OFF, INHERITED, NULL
强制这个
logger
必须从其父辈继承一个日志级别
- additivity 取值是一个布尔值,
true
或者false
配置 root 节点
标签下允许有0个或者多个
属性
- level 取值范围只能取
TRACE, DEBUG, INFO, WARN, ERROR, ALL, OFF
配置 appender 节点
属性
-
name
-
class 指定具体的实现类
实现类的类型是
PatternLayout
或PatternLayoutEncoder
class 属性可不填
如果想要往一个 logger 上绑定 appender,则使用以下方式
<logger name="HELLO" level="debug">
<appender-ref ref="FILE" />
<appender-ref ref="STDOUT" />
</logger>
变量替换
在
logback
中,支持以${varName}
来引用变量
定义变量
-
logback.xml 中定义变量
<configuration> <property name="USER_HOME" value="/home/costom" /> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>${USER_HOME}/myApp.log</file> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="FILE" /> </root> </configuration>
-
通过大D参数来定义
java -DUSER_HOME="/home/costom" myapp
- 通过外部文件来定义
<configuration>
<property file="src/main/java/chapters/configuration/variables1.properties" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${USER_HOME}/myApp.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
- 外部文件也支持
classpath
中的文件
<configuration>
<property resource="resource1.properties" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${USER_HOME}/myApp.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
变量的作用域
-
local
local
作用域在配置文件内有效 -
context
context
作用域的有效范围延伸至logger context
-
system
system
作用域的范围最广,整个JVM
内都有效
为变量指定 scope
<configuration>
<property scope="context" name="nodeId" value="firstNode" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>/opt/${nodeId}/myApp.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
变量的默认值: 在引用一个变量时,如果该变量未定义,那么可以为其指定默认值,做法是
${aName:-golden}
Springboot分环境配置使用
测试环境application-dev.yml配置文件
logging:
#Linux下使用classpath:/logback-dev.xml
#Windows下使用./src/main/resources/logback-dev.xml
config: ./src/main/resources/logback-dev.xml
path: ./logs
level:
root: info
注意如果在application-dev.yml
配置了日志级别那么logback-dev.xml
的root
配置的级别将失效,项目启动日志级别将以application
中配置的级别为准。
在/src/main/resources
目录下创建logback-dev.xml
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!-- 属性文件:在properties或yml文件中找到对应的配置项 -->
<springProperty scope="context" name="logging.path" source="logging.path"/>
</configuration>
对项目中的某一个类指定专门的日志处理
假如项目中有一个schedule的任务调度类,我们需要做单独的日志处理,则配置如下:
<!--特殊功能单独appender 例如调度类的日志-->
<appender name="CLASS-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>
%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n
</pattern>
</encoder>
<!--滚动策略-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--路径-->
<fileNamePattern>${logging.path}/schedule.class.%d{yyyy-MM-dd}.log</fileNamePattern>
<MaxHistory>90</MaxHistory>
</rollingPolicy>
</appender>
<!--这里的name和业务类中的getLogger中的字符串是一样的-->
<logger name="schedule" level="INFO" additivity="true">
<appender-ref ref="CLASS-APPENDER" />
</logger>
注意logger
的name
就是private Logger LOGGER= LoggerFactory.getLogger("schedule");
中的字符串。
如果我们使用的是lomok插件,则schedule
指的是topic
@Slf4j(topic = "schedule")
public class ScheduleService{
}
示例
示例1
<?xml version="1.0" encoding="UTF-8"?>
<!--
scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
-->
<configuration scan="false" scanPeriod="60 seconds" debug="false">
<!-- 定义日志的根目录 -->
<property name="LOG_HOME" value="/app/log" />
<!-- 定义日志文件名称 -->
<property name="appName" value="atguigu-springboot"></property>
<!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<!--
日志输出格式:
%d表示日期时间,
%thread表示线程名,
%-5level:级别从左显示5个字符宽度
%logger{50} 表示logger名字最长50个字符,否则按照句点分割。
%msg:日志消息,
%n是换行符
-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</layout>
</appender>
<!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
<appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 指定日志文件的名称 -->
<file>${LOG_HOME}/${appName}.log</file>
<!--
当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。
-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--
滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动
%i:当文件大小超过maxFileSize时,按照i进行文件滚动
-->
<fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!--
可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每天滚动,
且maxHistory是365,则只保存最近365天的文件,删除之前的旧文件。注意,删除旧文件是,
那些为了归档而创建的目录也会被删除。
-->
<MaxHistory>365</MaxHistory>
<!--
当日志文件超过maxFileSize指定的大小是,根据上面提到的%i进行日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy
-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 日志输出格式: -->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern>
</layout>
</appender>
<!--
logger主要用于存放日志对象,也可以定义日志类型、级别
name:表示匹配的logger类型前缀,也就是包的前半部分
level:要记录的日志级别,包括 TRACE < DEBUG < INFO < WARN < ERROR
additivity:作用在于children-logger是否使用 rootLogger配置的appender进行输出,
false:表示只用当前logger的appender-ref,true:
表示当前logger的appender-ref和rootLogger的appender-ref都有效
-->
<!-- hibernate logger -->
<logger name="com.atguigu" level="debug" />
<!-- Spring framework logger -->
<logger name="org.springframework" level="debug" additivity="false"></logger>
<!--
root与logger是父子关系,没有特别定义则默认为root,任何一个类只会和一个logger对应,
要么是定义的logger,要么是root,判断的关键在于找到这个logger,然后判断这个logger的appender和level。
-->
<root level="info">
<appender-ref ref="stdout" />
<appender-ref ref="appLogAppender" />
</root>
</configuration>
示例2
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds">
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
<!--通过springProperty标签直接读取application.yml中数据库的配置-->
<springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
<springProperty scope="context" name="TAGS" source="spring.profiles.active"/>
<springProperty scope="context" name="APP_PORT" source="server.port"/>
<property name="LOG_DIR" value="./logs"/>
<property name="ENCODER_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} | %thread | %-5level | %logger{50} : %msg%n"/>
<!-- 活动文件的大小 -->
<property name="MAX_FILE_SIZE" value="150MB"/>
<!-- 保留的归档文件的最大数量 -->
<property name="MAX_HISTORY" value="30"/>
<!-- 控制所有归档日志文件的总大小 -->
<property name="TOTAL_SIZE_CAP" value="30GB"/>
<!--引入logback默认的console appender 配置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<!--用来设置上下文名称,每个logger都关联到logger上下文,默认上下文名称为default。但可以使用设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改-->
<contextName>${APP_NAME}</contextName>
<!--end-->
<!--输出debug级别日志到文件-->
<appender name="DEBUG_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 每天一归档 -->
<fileNamePattern>${LOG_DIR}/debug.%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!-- 单个日志文件最多 150MB, 30天的日志周期,最大不能超过30GB -->
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
<maxHistory>${MAX_HISTORY}</maxHistory>
<totalSizeCap>${TOTAL_SIZE_CAP}</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>${ENCODER_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 只打印DEBUG日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--输出info级别日志到文件-->
<appender name="INFO_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 每天一归档 -->
<fileNamePattern>${LOG_DIR}/info.%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!-- 单个日志文件最多 150MB, 30天的日志周期,最大不能超过30GB -->
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
<maxHistory>${MAX_HISTORY}</maxHistory>
<totalSizeCap>${TOTAL_SIZE_CAP}</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>${ENCODER_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 只打印INFO日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--输出error级别日志到文件-->
<appender name="ERROR_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 每天一归档 -->
<fileNamePattern>${LOG_DIR}/error.%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!-- 单个日志文件最多 150MB, 30天的日志周期,最大不能超过30GB -->
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
<maxHistory>${MAX_HISTORY}</maxHistory>
<totalSizeCap>${TOTAL_SIZE_CAP}</totalSizeCap>
</rollingPolicy>
<append>true</append>
<encoder>
<pattern>${ENCODER_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 只打印ERROR日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--输出warn级别日志到文件-->
<appender name="WARN_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 每天一归档 -->
<fileNamePattern>${LOG_DIR}/warn.%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!-- 单个日志文件最多 150MB, 30天的日志周期,最大不能超过30GB -->
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
<maxHistory>${MAX_HISTORY}</maxHistory>
<totalSizeCap>${TOTAL_SIZE_CAP}</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>${ENCODER_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 只打印WARN日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 异步输出日志 -->
<appender name ="ASYNC_ERROR" class= "ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref ="ERROR_LOG"/>
</appender>
<appender name ="ASYNC_WARN" class= "ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref ="WARN_LOG"/>
</appender>
<appender name ="ASYNC_INFO" class= "ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref ="INFO_LOG"/>
</appender>
<appender name ="ASYNC_DEBUG" class= "ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref ="DEBUG_LOG"/>
</appender>
<appender name="SQL_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 每天一归档 -->
<fileNamePattern>${LOG_DIR}/sql.%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!-- 单个日志文件最多 150MB, 30天的日志周期,最大不能超过30GB -->
<maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
<maxHistory>${MAX_HISTORY}</maxHistory>
<totalSizeCap>${TOTAL_SIZE_CAP}</totalSizeCap>
</rollingPolicy>
<append>true</append>
<encoder>
<pattern>${ENCODER_PATTERN}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<appender name ="ASYNC_SQL" class= "ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref ="SQL_LOG"/>
</appender>
<!--将sql日志打印到文件的同时传递到root logger-->
<logger name="jdbc.connection" level="ERROR" >
<appender-ref ref="ASYNC_SQL" />
</logger>
<logger name="jdbc.resultset" level="OFF">
<appender-ref ref="ASYNC_SQL" />
</logger>
<logger name="jdbc.audit" level="OFF">
<appender-ref ref="ASYNC_SQL" />
</logger>
<logger name="jdbc.sqlonly" level="OFF">
<appender-ref ref="ASYNC_SQL" />
</logger>
<logger name="jdbc.sqltiming" level="INFO">
<appender-ref ref="ASYNC_SQL" />
</logger>
<!-- MyBatis log configure -->
<logger name="com.apache.ibatis" level="INFO"/>
<logger name="org.mybatis.spring" level="DEBUG"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
<!-- 减少部分debug日志 -->
<logger name="druid.sql" level="INFO"/>
<logger name="org.apache.shiro" level="INFO"/>
<logger name="org.mybatis.spring" level="INFO"/>
<logger name="org.springframework" level="INFO"/>
<logger name="org.springframework.context" level="WARN"/>
<logger name="org.springframework.beans" level="WARN"/>
<logger name="com.baomidou.mybatisplus" level="INFO"/>
<logger name="org.apache.ibatis.io" level="INFO"/>
<logger name="org.apache.velocity" level="INFO"/>
<logger name="org.eclipse.jetty" level="INFO"/>
<logger name="io.undertow" level="INFO"/>
<logger name="org.xnio.nio" level="INFO"/>
<logger name="org.thymeleaf" level="INFO"/>
<logger name="springfox.documentation" level="INFO"/>
<logger name="org.hibernate.validator" level="INFO"/>
<logger name="com.netflix.loadbalancer" level="INFO"/>
<logger name="com.netflix.hystrix" level="INFO"/>
<logger name="com.netflix.zuul" level="INFO"/>
<logger name="de.codecentric" level="INFO"/>
<!-- cache INFO -->
<logger name="net.sf.ehcache" level="INFO"/>
<logger name="org.springframework.cache" level="INFO"/>
<!-- cloud -->
<logger name="org.apache.http" level="INFO"/>
<logger name="com.netflix.discovery" level="INFO"/>
<logger name="com.netflix.eureka" level="INFO"/>
<!-- 业务日志 -->
<Logger name="com.bison" level="DEBUG" />
<Logger name="com.bison.core.version" level="INFO"/>
<!-- 过滤日志 level=OFF可以关闭-->
<logger name="javax.activation" level="WARN" />
<logger name="javax.mail" level="WARN" />
<logger name="javax.xml.bind" level="WARN" />
<logger name="ch.qos.logback" level="WARN" />
<logger name="com.codahale.metrics" level="WARN" />
<logger name="com.ryantenney" level="WARN" />
<logger name="com.sun" level="WARN" />
<logger name="com.zaxxer" level="WARN" />
<logger name="io.undertow" level="WARN" />
<logger name="net.sf.ehcache" level="ERROR" />
<logger name="org.apache" level="WARN" />
<logger name="org.apache.catalina.startup.DigesterFactory" level="OFF"/>
<logger name="org.bson" level="WARN" />
<logger name="org.hibernate.validator" level="WARN" />
<logger name="org.hibernate" level="WARN" />
<logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/>
<logger name="org.springframework" level="WARN" />
<logger name="org.springframework.web" level="WARN" />
<logger name="org.springframework.security" level="WARN" />
<logger name="org.springframework.cache" level="WARN" />
<logger name="org.springframework.boot" level="WARN" />
<logger name="org.thymeleaf" level="WARN" />
<logger name="org.xnio" level="WARN" />
<logger name="springfox" level="WARN" />
<logger name="sun.rmi" level="WARN" />
<logger name="liquibase" level="WARN" />
<logger name="sun.rmi.transport" level="WARN" />
<logger name="com.alibaba.nacos.naming" level="WARN" />
<!-- LoggerContextListener 接口的实例能监听 logger context 上发生的事件,比如说日志级别的变化,可做日志级别变更穿透-->
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<!-- 日志输出级别 -->
<springProfile name="prod">
<root level="INFO">
<appender-ref ref="ASYNC_INFO" />
<appender-ref ref="ASYNC_WARN" />
<appender-ref ref="ASYNC_ERROR" />
</root>
<!-- 当为线上测试环境时用添加以下 -->
<root level="DEBUG">
<appender-ref ref="ASYNC_SQL" />
</root>
</springProfile>
</configuration>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?