Spring Boot Logging

2,337 阅读6分钟

日志作为任何项目必须要有的功能,Spring Boot 自然是对其提供了支持。

如图,spring-boot-starter 的依赖之一 spring-boot-starter-logging 就是 spring 提供日志解决方案。它采用 slf4j 日志门面框架作为接口屏蔽层,支持 logback、Log4j2、JUL(Java Util Logging) 等多个日志实现框架

关于日志门面框架日志实现框架,请参考java 生态下的日志框架

以下内容基于 spring boot 2.2.2f

Logging

Spring Boot Logging 为 JUL(Java Util Logging)、Log4J2、Logback提供了默认配置。默认将日志输出到控制台,当然你也可以通过配置,将日志输出到文件

通常,你不需要更改任何设置,Spring Boot 默认值就让日志框架正常工作。

日志格式

Spring Boot 默认会输出以下格式的日志

2019-03-05 10:57:51.112  INFO 45469 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.52
2019-03-05 10:57:51.253  INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-03-05 10:57:51.253  INFO 45469 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1358 ms

内容依次是

  • yyyy-MM-dd hh:mm:ss,SSS 格式的时间戳
  • 日志级别。可能值有 ERROR、WARN、INFO、DEBUG、TRACE
  • PID(进程号)
  • 分隔符(---)
  • [当前线程名称]
  • 类路径,通常为缩写
  • 日志信息
Logback 没有 FATAL ,它会被映射到 ERROR

输出到控制台

默认情况下,将记录 ERROR、WARN、INFO 这三个等级的消息,并将它们输出到控制台。

如果想要开启 debug 级别的消息,需要在 application.properties 中配置 debug=true

启用 debug 后,将配置一些核心记录器(Hibernate、Spring Boot)以输出更多信息。但并不是记录所有 DEBUG 级别的消息

颜色

如果您的终端支持ANSI,spring boot 会尝试使用彩色输出来提高可读性。

通过使用 %clr 转换字来配置颜色。在其最简单的形式中,转换器根据日志级别对输出进行着色,如以下示例所示: %clr(%5p)

日志级别对应的颜色

LevelColor
FATALRed
ERRORRed
WARNYellow
INFOGreen
DEBUGGreen
TRACEGreen

也可以手动指定颜色,例如指定日期为黄色 %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}

支持的颜色有

  • blue
  • cyan
  • faint
  • green
  • magenta
  • red
  • yellow

输出到文件

默认情况下,Spring Boot 仅将日志输出到控制台。如果还想输出到文件,则需要在 application.properties 中配置logging.file.namelogging.file.path

logging.file.namelogging.file.pathDescription
不配置不配置输出到控制台
文件名(绝对或相对路径)不配置输出到文件
不配置绝对或相对路径将spring.log写入指定的目录

与控制台输出一样,默认只记录 ERROR、WARN、INFO 这三个等级的消息

日志文件达到10 MB时会发生滚动,可以配置 logging.file.max-size 更改大小限制。默认归档日志文件将无限期保存,要加以限制请设置 logging.file.max-history 属性。如果还想进一步限制日志归档文件的总大小,需要设置logging.file.total-size-cap,当日志归档的总大小超过该阈值时,将删除日志文件。如果想要在应用程序启动时清理日志存档,需要配置logging.file.clean-history-on-start

记录器级别

所有支持的日志系统都可以在 application.properties 中通过 logging.level.<logger-name>=<level> 配置记录器的级别。

其中 是记录器的名称,值得注意的是根记录器的名称为 root,其他的记录器的名称一般是完整包名或类名

例如

logging.level.root=warn
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error

记录器组

application.properties 中 将多个相关记录器设置成一个分组,以便同时配置它们

例如

logging.group.tomcat=org.apache.catalina, org.apache.coyote, org.apache.tomcat
logging.level.tomcat=TRACE

Spring Boot 包含以下预定义的日志记录器组,你可以直接使用它们

NameLoggers
weborg.springframework.core.codec, org.springframework.http, org.springframework.web, org.springframework.boot.actuate.endpoint.web, org.springframework.boot.web.servlet.ServletContextInitializerBeans
sqlorg.springframework.jdbc.core, org.hibernate.SQL, org.jooq.tools.LoggerListener

自定义日志配置

通过在类路径下提供对应日志系统的配置文件,可以进一步自定义各种日志系统的配置

根据您的日志记录系统,将加载以下文件,存在多个配置文件时,按以下顺序加载

Logging SystemCustomization
Logbacklogback-spring.xml, logback-spring.groovy, logback-test.xml,logback.xml, or logback.groovy
Log4j2log4j2-spring.xml or log4j2.xml
JDK (Java Util Logging)logging.properties

spring 建议使用 -spring 后缀用于日志记录配置。如果使用标准配置名,Spring 将无法完全控制日志初始化。

通过配置 org.springframework.boot.logging.LoggingSystem 属性来强制使用特定的日志系统。值为日志实现的完全限定类名。将其设置为none 可以完全禁用 Spring Boot 的日志记录配置

由于日志记录是在创建ApplicationContext之前初始化的,所以不可能控制来自Spring @Configuration文件中的@PropertySources的日志记录。更改日志系统或完全禁用它的唯一方法是通过系统属性。

为了帮助进行自定义,一些其他属性从Spring环境转移到系统属性,如下表所示:

春季环境系统属性注释
logging.exception-conversion-wordLOG_EXCEPTION_CONVERSION_WORD记录异常时使用的转换字
logging.file.clean-history-on-startLOG_FILE_CLEAN_HISTORY_ON_START是否在启动时清除存档日志文件(如果启用了LOG_FILE)。(仅默认的Logback设置受支持。)
logging.file.nameLOG_FILE如果定义,它将在默认日志配置中使用。
logging.file.max-sizeLOG_FILE_MAX_SIZE最大日志文件大小(如果启用了LOG_FILE)。(仅默认的Logback设置受支持。)
logging.file.max-historyLOG_FILE_MAX_HISTORY要保留的最大归档日志文件数(如果启用了LOG_FILE)。(仅默认的Logback设置受支持。)
logging.file.pathLOG_PATH如果定义,它将在默认日志配置中使用。
logging.file.total-size-capLOG_FILE_TOTAL_SIZE_CAP要保留的日志备份的总大小(如果启用了LOG_FILE)。(仅默认的Logback设置受支持。)
logging.pattern.consoleCONSOLE_LOG_PATTERN控制台上使用的日志模式(stdout)。(仅默认的Logback设置受支持。)
logging.pattern.dateformatLOG_DATEFORMAT_PATTERN记录日期格式的附加模式。(仅默认的Logback设置受支持。)
logging.pattern.fileFILE_LOG_PATTERN文件中使用的日志模式(如果LOG_FILE已启用)。(仅默认的Logback设置受支持。)
logging.pattern.levelLOG_LEVEL_PATTERN呈现日志级别时使用的格式(默认%5p)。(仅默认的Logback设置受支持。)
logging.pattern.rolling-file-nameROLLING_FILE_NAME_PATTERN过渡日志文件名的模式(默认${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz)。(仅默认的Logback设置受支持。)
PIDPID当前进程ID(如果可能,并且尚未将其定义为OS环境变量时,将被发现)。

所有受支持的日志记录系统在解析其配置文件时都可以查阅系统属性

Logback 扩展

Spring Boot包含许多Logback扩展,可以帮助进行高级配置。您可以在 logback-spring.xml 配置文件中使用这些扩展

由于标准logback.xml配置文件加载太早,因此您不能在其中使用扩展名。您需要使用logback-spring.xml或定义一个logging.config属性

<springProfile>

使用 标签,您可以根据活动的 Spring 配置文件选择包括或排除配置部分

例如

<springProfile name="test">
    <!-- "test"配置文件处于活动状态时启用的配置 -->
</springProfile>

<springProfile name="dev | test">
    <!-- "dev" 或 "test" 配置文件处于活动状态时启用的配置 -->
</springProfile>

<springProfile name="!dev">
    <!-- "dev"配置文件不活动时启用的配置 -->
</springProfile>

<springProfile> 在<configuration>元素内的任何位置都支持

<springProperty>

如果您想从 Logback 配置文件中访问 application.properties 文件中的值,可以使用 <springProperty> 标签。该标签的工作方式类似于 Logback 的标准 <property> 标签。

springProperty 有4个属性

  • name : 变量名
  • scope : 从哪个环境上下文中获取属性
  • source : 获取哪个属性
  • defaultValue : 如果没有获取到属性,默认值是什么

使用方式如下

<springProperty name="fluentHost" scope="context" source="myapp.fluentd.host" defaultValue="localhost"/>
<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
    <remoteHost>${fluentHost}</remoteHost>
    ...
</appender>

spring boot 的默认 Logback 配置

源码

这4个xml就是 spring boot 的默认 Logback 配置,这也是我们即使不创建 logback.xml spring boot 也会为我们打印出丰富的信息的原因

logback-spring.xml

官方推荐使用 logback-spring.xml 而不是 logback.xml,spring 可以完全控制日志初始化过程,并且可以使用 spring 对 logback 的扩展支持

xml配置

<?xml version="1.0" encoding="UTF-8"?>

<!-- scan :开启"热更新" scanPeriod:"热更新"扫描周期,默认 60 seconds(60秒)-->
<configuration scan="true" scanPeriod="300 seconds">

    <!-- 引入颜色转换器 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>

    <!-- 自定义变量  name :变量名   scope : 在哪个环境中查找 source : 使用哪个属性 defaultValue :没找到时的默认值-->
    <springProperty name="env" scope="context" source="spring.profiles.active" defaultValue="env"/>

    <!-- 自定义变量,用于配置日志输出格式,这个格式是尽量偏向 spring boot 默认的输出风格
    %date:日期,默认格式 yyyy-MM-dd hhh:mm:ss,SSS 默认使用本机时区,通过 %d{yyyy-MM-dd hhh:mm:ss,SSS} 来自定义
    %-5level:5个占位符的日志级别,例如" info"、"error"
    %thread : 输出日志的线程
    %class : 输出日志的类的完全限定名,效率低
    %method : 输出日志的方法名
    %line : 输出日志的行号,效率低
    %msg : 日志消息内容
    %n : 换行
    -->
    <property name="LOG_PATTERN" value="%date %-5level ${PID:- } --- [%thread] %class.%method/%line : %msg%n"/>

    <!-- 彩色日志格式 -->
    <property name="LOG_PATTERN_COLOUR"
              value="${env} %date %clr(%-5level) %magenta(${PID:- }) --- [%thread] %cyan(%class.%method/%line) : %msg%n"/>


    <!--日志输出器. ch.qos.logback.core.ConsoleAppender : 输出到控制台-->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 配置日志输出格式 -->
            <pattern>${LOG_PATTERN_COLOUR}</pattern>
            <!-- 使用的字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 日志输出器。ch.qos.logback.core.rolling.RollingFileAppender : 滚动输出到文件 -->
    <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 活动中的日志文件名(支持绝对和相对路径) -->
        <file>logs/app1/app1.log</file>
        <!-- 滚动策略. ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy : 按照大小和时间滚动-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 何时触发滚动,如何滚动,以及滚动文件的命名格式
            %d : 日期,默认格式 yyyy-MM-dd,通过 %d{yyyy-MM-dd hhh:mm:ss} 来自定义格式。logback 就是通过 %d 知道了触发滚动的时机
            %i : 单个滚动周期内的日志文件的序列号
            .zip : 将日志文件压缩成zip。不想压缩,可以使用.log 结尾
            如下每天0点以后的第一日志请求触发滚动,将前一天的日志打成 zip 压缩包存放在 logs/app1/backup 下,并命名为 app1_%d_%i.zip
            -->
            <fileNamePattern>logs/app1/backup/app1_%d{yyyy-MM-dd}_%i.zip</fileNamePattern>

            <!--单个日志文件的最大大小-->
            <maxFileSize>10MB</maxFileSize>

            <!--删除n个滚动周期之前的日志文件(最多保留前n个滚动周期的历史记录)-->
            <maxHistory>30</maxHistory>
            <!-- 在有 maxHistory 的限制下,进一步限制所有日志文件大小之和的上限,超过则从最旧的日志开始删除-->
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <!-- 日志输出格式 -->
            <pattern>${LOG_PATTERN}</pattern>
            <!-- 使用的字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>


    <!-- 非 pord 环境下使用以下配置 -->
    <springProfile name="!prod">
        <!-- 记录器 name : 包名或类名, level : 要记录的日志的起始级别, additivity : 是否追加父类的 appender -->
        <logger name="com.wqlm.boot" level="debug" additivity="false">
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="ROLLING"/>
        </logger>
    </springProfile>



    <!-- 根记录器 -->
    <root level="info">
        <!-- 使用 STDOUT、ROLLING 输出记录的日志-->
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="ROLLING"/>
    </root>
</configuration>

相对路径的例子

如果只是进行简单的配置,使用 application.properties 配置文件就够了

# 当前活动的日志文件名
# logging.file.name=logs/app1/app.log
# 最多保留多少天的日志
# logging.file.max-history=30
# 单个日志文件最大容量
# logging.file.max-size=10MB
# dao 层设置成 debug 级别以显示sql
logging.level.com.wqlm.boot.user.dao=debug

参考文档

Spring Boot 官方文档