Springbooot配置logback日志详解及实践

一、 前言

日志框架的选型来说最快的肯定还是log4j2,TPS能提升6倍多。但是2021年12月10日,log4j2又被爆出高危漏洞。(前几个月刚开会说用log4j2,淦!赶紧又换回来了 )

看来不愧是SpringBoot默认的日志实现,logback还是相对稳定的。

现在还是来详细弄一弄logback!之前也没有仔细研究过。

项目文件在GitHub(欢迎star⭐):
https://github.com/Gang-bb/Gangbb-SpringBoot

二、使用详解

1. logback介绍

官方文档:http://logback.qos.ch/

Logback是由log4j创始人设计的另一个开源日志组件。它当前分为下面下个模块:

  • logback-core:其它两个模块的基础模块
  • logback-classic:它是log4j的一个改良版本,同时它完整实现了slf4j API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging
  • logback-access:访问模块与Servlet容器集成提供通过Http来访问日志的功能

Logback 日志级别比较简单,从严重到普通依次是:

  • ERROR
  • WARN
  • INFO
  • DEBUG
  • TRACE

2. logback配置

版本信息:

Springboot—2.6.1

Logback—1.2.7

2.1 基本配置

SpringBoot工程自带 Logbackslf4j的依赖,所以重点放在编写配置文件上,需要引入什么依赖,日志依赖冲突统统都不需要我们管了。

默认的 Logback 配置文件名有两种:

  • logback.xml:这种配置文件会直接被日志框架加载。
  • logback-spring.xml:这种配置文件不会被日志框架直接加载,而是由 Spring Boot 去解析日志配置,可以使用 Spring Boot 的高级 Profile 功能。

如果两个文件都不存在,logback用BasicConfigurator自动对自己进行配置,这会导致记录输出到控制台。

Spring Boot 中为 Logback 提供了四个默认的配置文件,位置在 org/springframework/boot/logging/logback/,分别是:

  • defaults.xml:提供了公共的日志配置,日志输出规则等。
  • console-appender.xml:使用 CONSOLE_LOG_PATTERN 添加一个ConsoleAppender。
  • file-appender.xml:添加一个 RollingFileAppender。
  • base.xml:为了兼容旧版 Spring Boot 而提供的。

可以通过 include 引入 Spring Boot 已经提供的配置文件,也可以自定义。

2.2 Logback 配置项详解

如果需要自定义 logback.xml 文件,可以在自定义时使用这些默认的配置文件,也可以不使用。一个典型的 logback.xml 文件如下(resources/logback.xml):

(1)根节点configuration,包含下面三个属性:

  • scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
  • scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
  • debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!--...其他配置暂时省略--> 
</configuration>

(2)子节点contextName:用来设置上下文名称,每个logger都关联到logger上下文,默认上下文名称为default。但可以使用contextName设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改。

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <contextName>myAppName</contextName> 
    <!--...其他配置暂时省略--> 
</configuration>

(3)子节点property :用来定义变量值,它有两个属性name和value,通过property定义的值会被插入到logger上下文中,可以使“${}”来使用变量。

  • name: 变量的名称
  • value: 的值时变量定义的值

例如:

<configuration scan="true" scanPeriod="60 seconds" debug="false"> 
   <property name="APP_Name" value="myAppName" /> 
   <contextName>${APP_Name}</contextName> 
   <!--...其他配置暂时省略--> 
</configuration>

(4)子节点timestamp:获取时间戳字符串,他有两个属性keydatePattern

  • key:标识此timestamp 的名字。
  • datePattern:设置将当前时间(解析配置文件的时间)转换为字符串的模式,遵循java.txt.SimpleDateFormat的格式。

例如:

<configuration scan="true" scanPeriod="60 seconds" debug="false"> 
	<timestamp key="timestamp_string" datePattern="yyyyMMdd'T'HHmmss"/> 
    <contextName>${timestamp_string}</contextName> 
    <!-- 其他配置省略--> 
</configuration>

(5)子节点appender:负责写日志的组件,它有两个必要属性nameclass

  • name:指定appender名称

  • class:指定appender的全限定名,分类

    • ch.qos.logback.core.ConsoleAppender:把日志输出到控制台,有以下子节点:
      • < encoder>:对日志进行格式化。(具体参数稍后讲解 )
      • < target>:字符串System.out(默认)或者System.err(区别不多说了)

    例如:

    <configuration> 
       <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
          <encoder> 
             <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern> 
          </encoder> 
       </appender> 
    
       <root level="DEBUG"> 
          <appender-ref ref="STDOUT" /> 
       </root> 
    </configuration>
    

    上述配置表示把>=DEBUG级别的日志都输出到控制台

    • ch.qos.logback.core.FileAppender:把日志添加到文件,有以下子节点:

      • < file>:被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。
      • < append>:如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true。
      • < encoder>:对记录事件进行格式化。
      • < prudent>:如果是 true,日志会被安全的写入文件,即使其他的FileAppender也在向此文件做写入操作,效率低,默认是 false。

    例如:

    <configuration> 
    	<appender name="FILE" class="ch.qos.logback.core.FileAppender"> 
    		<file>testFile.log</file> 
    	<append>true</append> 
    	<encoder> 
    		<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> 
    	</encoder> 
    	</appender> 
    
    	<root level="DEBUG"> 
    	<appender-ref ref="FILE" /> 
    	</root> 
    </configuration>
    

    上述配置表示把>=DEBUG级别的日志都输出到testFile.log

    • ch.qos.logback.core.rolling.RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。有以下子节点:

      • < file>:被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。

      • < append>:如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true。

      • < encoder>:对记录事件进行格式化。负责两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输出流。PatternLayoutEncoder 是唯一有用的且默认的encoder ,有一个节点,用来设置日志的输入格式。使用“%”加“转换符”方式,如果要输出“%”,则必须用“\”对“%”进行转义。

      • < rollingPolicy>:当发生滚动时,决定RollingFileAppender的行为,涉及文件移动和重命名。属性class定义具体的滚动策略类

        • < rollingPolicy class=“ch.qos.logback.core.rolling.TimeBasedRollingPolicy”> : 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。有以下子节点:
          • < fileNamePattern>:必要节点,包含文件名及“%d”转换符,“%d”可以包含一个java.text.SimpleDateFormat指定的时间格式,如:%d{yyyy-MM}。如果直接使用 %d,默认格式是 yyyy-MM-dd。
          • RollingFileAppender的file字节点可有可无,通过设置file,可以为活动文件和归档文件指定不同位置,当前日志总是记录到file指定的文件(活动文件),活动文件的名字不会改变;如果没设置file,活动文件的名字会根据fileNamePattern 的值,每隔一段时间改变一次。“/”或者“\”会被当做目录分隔符。
          • < maxHistory>:可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每个月滚动,且< maxHistory>是6,则只保存最近6个月的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除。

        例如:

        <configuration> 
            <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
                <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
                    <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern> 
                    <maxHistory>30</maxHistory> 
                </rollingPolicy> 
                <encoder> 
                    <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> 
                </encoder> 
            </appender> 
        
            <root level="DEBUG"> 
                <appender-ref ref="FILE" /> 
            </root> 
        </configuration>
        

        备注:上述配置表示每天生成一个日志文件,保存30天的日志文件。

        • < rollingPolicy class=“ch.qos.logback.core.rolling.FixedWindowRollingPolicy”> :根据固定窗口算法重命名文件的滚动策略。有以下子节点:
          • < minIndex>:窗口索引最小值
          • < maxIndex>:窗口索引最大值,当用户指定的窗口过大时,会自动将窗口设置为12
          • < fileNamePattern>:必须包含“%i”例如,假设最小值和最大值分别为1和2,命名模式为 mylog%i.log,会产生归档文件mylog1.log和mylog2.log。还可以指定文件压缩选项,例如,mylog%i.log.gz 或者 没有log%i.log.zip
        • < triggeringPolicy class=“ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy”> :查看当前活动文件的大小,如果超过指定大小会告知RollingFileAppender 触发当前活动文件滚动。只有一个节点:
          • < triggeringPolicy >: 告知 RollingFileAppender 合适激活滚动。
          • < maxFileSize>:这是活动文件的大小,默认值是10MB。
          • < prudent>:当为true时,不支持FixedWindowRollingPolicy。支持TimeBasedRollingPolicy,但是有两个限制,1不支持也不允许文件压缩,2不能设置file属性,必须留空。
        <configuration> 
        	<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
        		<file>test.log</file> 
        
        		<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> 
        			<fileNamePattern>tests.%i.log.zip</fileNamePattern> 
        			<minIndex>1</minIndex> 
        			<maxIndex>3</maxIndex> 
        		</rollingPolicy> 
        
        		<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> 
        			<maxFileSize>5MB</maxFileSize> 
        		</triggeringPolicy> 
        		<encoder> 
        			<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> 
        		</encoder> 
        	</appender> 
        
        	<root level="DEBUG"> 
        		<appender-ref ref="FILE" /> 
        	</root> 
        </configuration>
        

    ​ 备注:上述配置表示按照固定窗口模式生成日志文件,当文件大于5MB时,生成新的日志文件。窗口大小是1到3,当保存了3个归档文件后,将覆盖最早的日志。

    • 还有SocketAppender、SMTPAppender、DBAppender、SyslogAppender、SiftingAppender,并不常用

    (6)子节点logger:用来设置某一个包或具体的某一个类的日志打印级别、以及指定< appender>。< logger>仅有一个name属性,一个可选的level和一个可选的addtivity属性。可以包含零个或多个< appender-ref>元素,标识这个appender将会添加到这个logger

    • name:用来指定受此loger约束的某一个包或者具体的某一个类。

    • level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。如果未设置此属性,那么当前loger将会继承上级的级别。

    • addtivity:是否向上级loger传递打印信息。默认是true。

    (7)子节点root:它也是< logger>元素,但是它是根logger,是所有< logger>的上级。只有一个level属性,因为name已经被命名为"root",且已经是最上级了。level: 用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL和OFF,不能设置为INHERITED或者同义词NULL。 默认是DEBUG。

2.3 Logback配置打印信息着色

配置文件片段截取:

<!-- 控制台输出格式 -->
<property name="console.log.pattern" value="%red(%d{yyyy-MM-dd HH:mm:ss.SSS}) %green([%thread]) %highlight(%-5level) %boldMagenta([%logger{36}]) - %cyan(%msg%n)" />


<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
   <encoder>
      <pattern>${console.log.pattern}</pattern>
   </encoder>
</appender>

官方文档关于该部分介绍:

http://logback.qos.ch/manual/layouts.html#coloring

支持颜色:

image-20211213161557314

其他自定义颜色貌似是支持的,自行查看文档或者谷歌百度!

注意事项:

  • 第一点,颜色%black %red等等 ,需要用括号将你要显示本颜色的子模块括起来

  • 第二点,%red颜色等,前面要与上一个模块 空格隔开

示例打印着色效果:

image-20211213161713920

PS:虽然有点花里胡哨的,但是个人感觉比原来的白白一片看着舒服多了~

2.4 不同环境配置不同的日志级别

方法一:读取 spring 配置文件中的值

logback.xml 早于 application.yml 加载,logback-spring.xml 晚于 application.yml 加载,如果 logback 配置需要使用 application.yml 中的属性,需要命名为 logback-spring.xml。

现在采用 logback-spring.xml 文件来读取配置文件 application-${profile}.properties 中的属性值。logback 需要使用 标签才可使用 application.properties 中的属性,当配置文件中不存在属性值时,也可以设置默认值,示例如下所示。

<!-- 读取 application.properties 中的 log.level 属性,如果没有配置,默认 INFO -->
<springProperty name="LOG_LEVEL" source="log.level" defaultValue="INFO"/>

<logger name="com.test.svc" level="${LOG_LEVEL}" additivity="false">
    <appender-ref ref="ASYNC"/>
    <appender-ref ref="STDOUT"/>
</logger>

方法二:加载指定的配置模块

如下配置中,< springProfile name=“dev”> 中的 name,读取的是 spring.profiles.active 配置项的值,不设置默认为 default。
如下两条的意思是,当 spring.profiles.active 配置为 dev 的时候,包裹在其中的部分配置被加载。spring.profiles.active 没有配置,或者配置为 default 的时候,包裹在其中的日志设置内容被加载。如果有其他环境 test、prod、release 等,仿照如此配置即可。name 后面还可以跟表达式。

<springProfile name="dev">
        <!-- 开发环境时激活 -->
        <logger name="com.test.svc" level="DEBUG" additivity="false">
            <appender-ref ref="ASYNC"/>
            <appender-ref ref="STDOUT"/>
        </logger>
</springProfile>
<springProfile name="default">
        <!-- 默认环境时激活 -->
        <logger name="com.test.svc" level="INFO" additivity="false">
            <appender-ref ref="ASYNC"/>
            <appender-ref ref="STDOUT"/>
        </logger>
</springProfile>

2.5 logback 高级特性异步输出日志

之前的日志配置方式是基于同步的,每次日志输出到文件都会进行一次磁盘IO。采用异步写日志的方式而不让此次写日志发生磁盘IO,阻塞线程从而造成不必要的性能损耗。异步输出日志的方式很简单,添加一个基于异步写日志的appender,并指向原先配置的appender即可

 <!-- 异步输出 -->
    <appender name="ASYNC-INFO" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>256</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="INFO-LOG"/>
    </appender>

    <appender name="ASYNC-ERROR" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>256</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="ERROR-LOG"/>
    </appender>

2.6 完整配置示例

Spingboot项目下的resources/logback-spring.xml文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 一、根节点<configuration>,包含下面三个属性-->
<!--1.scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true-->
<!--2.scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。-->
<!--3.debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。-->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <!-- 日志存放路径 -->
	<property name="log.path" value="./logback/logs" />
    <!-- 控制台输出格式 -->
	<property name="console.log.pattern" value="%red(%d{yyyy-MM-dd HH:mm:ss.SSS}) %green([%thread]) %highlight(%-5level) %boldMagenta([%logger{60}]) - %cyan(%msg%n)" />
    <!-- 文件输出格式 -->
    <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level [%logger{36}] - %msg%n"/>

	<!-- 控制台输出 -->
	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>${console.log.pattern}</pattern>
		</encoder>
	</appender>

	<!-- 系统 INFO 日志文件输出 -->
	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
	    <file>${log.path}/sys-info.log</file>
        <!-- 循环政策:基于时间创建日志文件 -->
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志文件名格式 -->
			<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
			<!-- 日志最大的历史 60天 -->
			<maxHistory>60</maxHistory>
		</rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- 过滤的级别 -->
            <level>INFO</level>
            <!--DENY:表示不用看后面的过滤器了,这里就给拒绝了,不作记录。-->
            <!--NEUTRAL:表示需不需要记录,还需要看后面的过滤器。若所有过滤器返回的全部都是NEUTRAL,那么需要记录日志。-->
            <!--ACCEPT:表示不用看后面的过滤器了,这里就给直接同意了,需要记录。-->
            <!-- 匹配时的操作:接收(记录) -->
            <onMatch>ACCEPT</onMatch>
            <!-- 不匹配时的操作:拒绝(不记录) -->
            <onMismatch>DENY</onMismatch>
        </filter>
	</appender>

    <!-- 系统 error 日志文件输出 -->
	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
	    <file>${log.path}/sys-error.log</file>
        <!-- 循环政策:基于时间创建日志文件 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志文件名格式 -->
            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
			<!-- 日志最大的历史 60天 -->
			<maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- 过滤的级别 -->
            <level>ERROR</level>
			<!-- 匹配时的操作:接收(记录) -->
            <onMatch>ACCEPT</onMatch>
			<!-- 不匹配时的操作:拒绝(不记录) -->
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!--*********异步输出日志配置*********-->

    <!-- 异步输出 -->
    <appender name="ASYNC-INFO" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>256</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="file_info"/>
    </appender>

    <appender name="ASYNC-ERROR" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>256</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="file_error"/>
    </appender>

	
    <!--*********设置一些包的打印级别,过滤一些无用信息*********-->

	<!-- Spring日志级别控制  -->
	<logger name="org.springframework" level="info" />
    <logger name="_org.springframework" level="info" />

    <!--  默认环境日志级别  -->
    <springProfile name="default">
        <!--日志文件打印日志级别-->
        <root level="debug">
            <appender-ref ref="file_info" />
            <appender-ref ref="file_error" />
            <appender-ref ref="console" />
        </root>
    </springProfile>

    <!--  开发环境日志级别  -->
    <springProfile name="dev">
        <!--日志文件打印日志级别-->
        <root level="debug">
            <appender-ref ref="file_info" />
            <appender-ref ref="file_error" />
            <appender-ref ref="console" />
        </root>
    </springProfile>

    <!--  测试环境日志级别  -->
    <springProfile name="test">
        <!--日志文件打印日志级别-->
        <root level="info">
            <appender-ref ref="file_info" />
            <appender-ref ref="file_error" />
            <appender-ref ref="console" />
        </root>
    </springProfile>


    <!--  线上环境日志级别  -->
    <springProfile name="prod">
        <!--日志文件打印日志级别-->
        <root level="info">
            <appender-ref ref="file_info" />
            <appender-ref ref="file_error" />
            <appender-ref ref="console" />
        </root>
    </springProfile>


</configuration> 

项目启动后打印:

image-20211213175155040

如果命名为logback.xml,启动项目会打印logback的加载配置日志:

image-20211213175247139

如此配置的文件保存效果:

image-20211213170612206

引流2

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值