日志输出 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 内部运行流程

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 会使用 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>

posted on 2022-02-01 17:31  何苦->  阅读(366)  评论(0)    收藏  举报

导航