Bootstrap

【SpringBoot】【log】 自定义logback日志配置

前言:默认情况下,SpringBoot内部使用logback作为系统日志实现的框架,将日志输出到控制台,不会写到日志文件。如果在application.properties或application.yml配置,这样只能配置简单的场景,保存路径、日志格式等。复杂的场景(区分 info 和 error 的日志、每天产生一个日志文件等)满足不了,只能自定义配置文件logback-spring.xml。

一、application.properties系统配置logback日志
1.1、SpringBoot默认的日志配置
日志记录器(Logger)的行为是分等级的,日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出。

默认情况下,SpringBoot内部使用logback作为系统日志实现的框架,将日志输出到控制台,不会写到日志文件。Spring boot从控制台打印出来的日志级别默认只有INFO及以上级别,可以在application.properties中修改日志级别logging.level.root=WARN。

SpringBoot默认配置好了日志, 只要启动 Spring Boot 项目就会在控制台输出日志信息。

 从上图可以看到,日志输出的内容如下:

时间日期:精确到毫秒

日志级别:ERROR,WARN,INFO,DEBUG,TRACE

进程ID:

分隔符:— 标识实际日志的开始

线程名:方括号括起来(可能会截断控制台输出)

Logger名:通常使用源代码的类名

日志内容:

控制台格式化输出内容:

# 格式化,只输出日期和内容
logging.pattern.console= "%d -%p -%m" %n


打印参数: Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,如下:

%m       输出代码中指定的消息
%p        输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL 
%r         输出自应用启动到输出该log信息耗费的毫秒数 
%c        输出所属的类目,通常就是所在类的全名 
%t         输出产生该日志事件的线程名 
%n        输出一个回车换行符,Windows平台为“\\r\\n”,Unix平台为“\\n” 
%d        输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比                     如%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2018年6月15日22:10:28,921 
%l         输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举                     例:estlog4.main(TestLog4.java: 10)

1.2、添加依赖
Spring Boot为我们提供了很多默认的日志配置,所以,只要将spring-boot-starter-logging作为依赖加入到pom.xml,则“开箱即用”。实际开发中我们不需要直接添加该依赖,你会发现spring-boot-starter其中包含了 spring-boot-starter-logging,该依赖内容就是 Spring Boot 默认的日志框架 logback。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
</dependency>
1.3、application.properties简单配置日志相关属性
下面介绍几种在application.properties就可以配置的日志相关属性。

(1)控制台输出

Spring Boot中默认配置INFO、WARN和ERROR级别的日志只输出到控制台。

我们可以在application.properties中修改日志级别logging.level.root=WARN,这样核心Logger(包含嵌入式容器、hibernate、spring)会输出更多内容,还有自己应用的日志就会输出为DEBUG级别。

(2)文件输出

①使用application.properties默认配置

默认情况下,Spring Boot将日志输出到控制台,不会写到日志文件。如果要编写除控制台输出之外的日志文件,则需在application.properties中设置logging.file或logging.path属性。

logging.file:设置文件,可以是绝对路径,也可以是相对路径。如:logging.file=my.log

logging.path:设置目录,会在该目录下创建spring.log文件,并写入日志内容,如:logging.path=/var/log

如果只配置 logging.file,会在项目的当前路径下生成一个 xxx.log 日志文件;

如果只配置 logging.path,在 /var/log文件夹生成一个日志文件为 spring.log。

注:二者不能同时使用,如若同时使用,则只有logging.file生效

默认情况下,日志文件的大小达到10MB时会切分一次,产生新的日志文件,默认级别为:ERROR、WARN、INFO。

②使用logback-spring.xml自定义配置

如果在application.properties或application.yml配置,这样只能配置简单的场景,保存路径、日志格式等。复杂的场景(区分 info 和 error 的日志、每天产生一个日志文件等)满足不了,只能自定义logback配置,SpringBoot官方推荐使用logback-spring.xml作为logback框架的自定义日志配置文件。

1.4、两种配置方式总结
SpringBoot工程自带 logback和 slf4j的依赖,所以重点放在编写配置文件上:

application.properties或 application.yml (系统层面)

logback-spring.xml(自定义文件方式)

第一种方式比较简单,可做的事情也比较简单,比如:只能配置日志文件的输出路径、日志文件的格式、日志的级别等。

第二种方式比较复杂,对日志的处理比较好,生产上推荐这种,运行维护好。如有以下需求:

       a、区分 debug、info、error 等类型的日志,并分别输出到不同的日志文件。

      b、对日志文件进行维护,如每天产生一个日志文件,并设置日志文件的大小和保留天数等。

二、自定义日志配置logback-spring.xml
由于日志服务一般都在ApplicationContext创建前就初始化了,它并不是必须通过Spring的配置文件控制。因此通过系统属性和传统的Spring Boot外部配置文件依然可以很好的支持日志控制和管理。在类路径下放置自定义日志配置xml文件,SpringBoot就不会使用它本身的默认日志配置了。

2.1、日志记录框架的默认自定义配置文件名称
下图是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

2.2、SpringBoot推荐使用logback-spring.xml
SpringBoot官方推荐使用logback-spring.xml作为logback框架的自定义日志配置文件(例如:使用logback-spring.xml而不是logback.xml),因为带-spring后缀的配置文件可以使用SpringBoot提供的一些高级功能,如profile多环境日志输出。

将所有日志都存储在一个文件中文件大小也随着应用的运行越来越大并且不好排查问题,正确的做法应该是将 error日志和其他系统输出日志分开,并且不同级别的日志根据时间段进行记录存储。

在 src/main/resources 下创建 logback-spring.xml 文件,分开记录系统输出日志和Error日志:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
   
     <!--彩色日志输出格式-->
    <property name="CONSOLE_LOG_PATTERN" value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%level){blue} %clr(${PID}){magenta} %clr([%thread]){orange} %clr(%logger){cyan} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
    <!--非彩色日志输出格式-->
    <property name="PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
 
    <!--dev文件路径:src同级目录logs,如果上级目录不存在会自动创建-->
    <property name="DEV_FILE_PATH" value="./logs" />
    <!-- pro文件路径 -->
    <property name="PRO_FILE_PATH" value="/opt/prod/logs" />
 
    <!-- 控制台输出 -->
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
    </appender>
 
    <!-- 按照每天生成输出日志文件 -->
    <appender name="fileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程,%-5level:级别从左显示五个字符宽度,%logger{36}:logger是class的全名,后面的数字代表限制最长的字符,%msg:日志消息,%n换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
        <!--滚动策略按照时间滚动-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- rollover daily 文件名称 -->
            <fileNamePattern>${DEV_FILE_PATH}/output-%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- each file should be at most 10MB, keep 60 days worth of history, but at most 2GB -->
            <!--单个文件大小-->
            <maxFileSize>10MB</maxFileSize>
            <!--日志文件保留天数-->
            <maxHistory>60</maxHistory>
            <!--用来指定日志文件的上限大小,到了这个值就会删除旧日志-->a
            <totalSizeCap>2GB</totalSizeCap>
        </rollingPolicy>
    </appender>
 
    <!-- 按照每天生成错误日志文件 -->
    <appender name="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 此日志文件只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
        <!--输出日志到src同级目录logs中的error.log文件中-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--基于大小和时间的轮转策略,当日志内容超出文件大小限制后,会自动生成一个文件来继续记录和重命名-->
            <fileNamePattern>${DEV_FILE_PATH}/error-%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- each file should be at most 10MB, keep 60 days worth of history, but at most 2GB -->
            <maxFileSize>10MB</maxFileSize>
            <maxHistory>60</maxHistory>
            <totalSizeCap>2GB</totalSizeCap>
        </rollingPolicy>
    </appender>
 
    <!--开发环境:打印控制台-->
    <springProfile name="dev">
        <root level="INFO">
            <appender-ref ref="consoleAppender" />
            <appender-ref ref="fileAppender" />
            <appender-ref ref="errorAppender" />
        </root>
    </springProfile>
 
    <!--生产环境:输出到文件-->
    <springProfile name="pro">
        <!-- root日志以INFO级别输出,指定日志信息输出到哪个地方-->
        <root level="INFO">
            <appender-ref ref="consoleAppender" />
            <appender-ref ref="fileAppender" />
            <appender-ref ref="errorAppender" />
        </root>
    </springProfile>
 
</configuration>
 输出结果:

非彩色日志:

彩色日志:

2.3、logback配置文件的节点属性简介
Appender是负责写日志的组件,设置日志信息的去向,常用的有以下几个:

ch.qos.logback.core.ConsoleAppender (控制台)

ch.qos.logback.core.rolling.RollingFileAppender (文件大小到达指定尺寸的时候产生一个新文件)

ch.qos.logback.core.FileAppender (文件)

其中,<springProfile> 标签的 name 属性对应 application.properties 中的 spring.profiles.active 的配置。即 spring.profiles.active 的值可以看作是日志配置文件中对应的 springProfile 是否生效的开关。

(1) logger

用来设置某一个包或者具体的某一个类的日志打印级别、以及指定appender。logger仅有一个name属性,一个可选的level和一个可选的additivity属性。

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

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

additivity:是否向上级logger传递打印信息。默认是true。

logger可以包含零个或多个appender-ref元素,标识这个appender将会添加到这个logger。

(2)root

也是logger元素,但是它是根logger。只有一个level属性,因为已经被命名为”root”。

level:用来设置打印级别,大小写无关:TRACE,DEBUG,INFO,WARN,ERROR,ALL和OFF,不能设置为INHERITED或者同义词NULL。默认是DEBUG。

root可以包含零个或多个appender-ref元素,标识这个appender将会添加到这个logger。rootLogger指定日志信息输出到哪个地方,可以同时指定多个输出目的地。

 三、<springProfile>多环境输出日志文件
SpringBoot官方建议使用logback-spring.xml作为logback框架的自定义日志配置文件,使用logback-spring.xml而不是logback.xml,因为带-spring后缀的配置文件可以使用使用Spring扩展profile支持,提供profile多环境日志输出得功能。

Logback 配置文件中的 <springProfile >节点指令允许您根据配置文件激活参数(active) 选择性的包含和排查部分配置信息。根据不同环境来定义不同的日志输出,在 logback-spring.xml中使用 <springProfile>节点来定义,方法如下:

    <!--开发环境:打印控制台-->
    <springProfile name="dev">
       
        <!--用来设置某一个包或者具体的某一个类的日志打印级别,可以让控制台输出debug-->
        <logger name="com.hs" level="debug" />
        <!--
            root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性,可以包含零个或多个appender元素。
        -->
        <root level="INFO">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="WARN_FILE" />
            <appender-ref ref="ERROR_FILE" />
        </root>
    </springProfile>
 
    <!--生产环境:输出到文件-->
    <springProfile name="pro">
        <root level="INFO">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="DEBUG_FILE" />
            <appender-ref ref="INFO_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="WARN_FILE" />
        </root>
    </springProfile>
为何root配置的INFO,logger特殊指定的包/类日志DEBUG级别,最后也能打印出来?

答案:因为没有设置addtivity="false" ,如下图即可。

 <logger name="包名/类名" level="DEBUG" addtivity="false" />
logger有一个属性addtivity="true" 默认就是true,标识向上级传递日志(INFO是DEBUG的上级)。只有显示指定为false时,才不会向上级输出。

(1)可以启动服务的时候指定 profile (如不指定使用默认),如指定prod 的方式为:

java -jar xxx.jar –spring.profiles.active=prod

(2)也可以在yml配置文件中指明当前环境是什么环境,否则启动会报错,如下:

四、 解决 logback.xml 配置文件不生效的问题
问题描述:在resources目录下建立logback-spring配置文件后,只能打印控制台日志,不能创建日志文件。疯狂修改配置文件的内容,就连常用的重启、清除缓存都试过了,但是日志配置依然不生效。所以就查找原因,既然不是配置文件内部的问题,那就是配置文件根本就没起效果。

原因追溯:意外发现SpringBoot项目打包后的target/classes没有包含logback-spring.xml,这就是

logback.xml 配置不起作用的根本原因。

 然后发现之前在pom.xml中加了个resources目录下文件的过滤配置,没有保留logback日志文件:

        <!--添加打包过滤的配置文件规则,定义资源过滤,用来保证配置文件打包生成到target中-->
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <!-- 开启过滤替换功能,用于替换resources里的变量-->
                <filtering>true</filtering>
                <!--按需保留需要的profile文件-->
                <includes>
                    <include>application-${spring.profiles.active}.yaml</include>
                    <include>application.properties</include>
                    <include>application.properties</include>
                </includes>
            </resource>
        </resources>
解决方案:保留logback-spring.xml和logback.xml配置文件

        <!--添加打包过滤的配置文件规则,定义资源过滤,用来保证配置文件打包生成到target中-->
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <!-- 开启过滤替换功能,用于替换resources里的变量-->
                <filtering>true</filtering>
                <!--按需保留需要的profile文件-->
                <includes>
                    <include>application-${spring.profiles.active}.yaml</include>
                    <include>application.properties</include>
                    <include>application.properties</include>
                    <include>logback.xml</include>
                    <include>logback-spring.xml</include>
                </includes>
            </resource>
        </resources>
现在target-classes下有了logback.xml配置文件,相关日志正常生效。


                        
原文链接:https://blog.csdn.net/CSDN2497242041/article/details/122596582

;