日志输出 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 相关的类,这样在需要将日志框架切换为其它日志框架时,无需改动代码。LoggerFactorygetLogger() 方法接收一个参数,以这个参数决定 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.wsllogger,是命名为 com.wsl.testlogger 的父亲,是命名为 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 内部运行流程

image-20230425144324464

  1. 获得过滤器链条
  2. 检查日志级别以决定是否继续打印
  3. 创建一个 LoggingEvent 对象
  4. 调用 Appenders
  5. 进行日志信息格式化
  6. 发送 LoggingEvent 到对应的目的地

logback 配置

配置方式

  • 编程式配置
  • xml 格式
  • groovy 格式

logback 在启动时,根以下步骤寻找配置文件:

  • classpath 中寻找 logback-test.xml文件
  • 如果找不到 logback-test.xml,则在 classpath 中寻找 logback.groovy 文件
  • 如果找不到 logback.groovy,则在 classpath 中寻找 logback.xml文件
  • 如果上述的文件都找不到,则 logback 会使用 JDKSPI 机制查找 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);
  ...
}

也可以在配置文件中,指定configurationdebug 属性为 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>

也可以通过 LoggerContextsetPackagingDataEnabled(boolean)方法来开启

 LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
 lc.setPackagingDataEnabled(true);

配置文件格式

基本格式: configuration节点下配置appenderloggerroot

根节点是 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 指定具体的实现类

    实现类的类型是 PatternLayoutPatternLayoutEncoder 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.xmlroot配置的级别将失效,项目启动日志级别将以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>

注意loggername就是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>

posted on   何苦->  阅读(278)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示