Spring Boot - 日志记录

[TOC]

简介

Spring Boot 内部使用的日志框架为Commons Logging,但是 Commons Logging 的内部具体实现可以由用户自行指定。
默认已提供了对 Java Utils LoggingLog4J2Logback 日志库的相关配置。
无论选择以上哪一个日记库,Spring Boot 都预置了将日志输出到控制台以及可选的文件上。

如果项目配置使用起步依赖(Starters),那么默认情况下,Spring Boot 使用的日记记录库为 Logback。

因此,本文主要介绍在 Spring Boot 中使用 Logback 进行日志记录。

依赖导入

前面已经介绍过,Spring Boot 默认使用的日志框架为 Apache Commons Logging

在 Spring 4.x(也即 Spring Boot 1.x)时,我们需要手动进行依赖导入。
但是在 Spring 5.x(也即 Spring Boot 2.x)时,该依赖由 Spring Framework 模块 spring-jcl 提供。

当我们项目使用各种起步依赖(Starter)时,spring-jcl 模块包含在 spring-boot-starter-logging 中,理论上我们需要手动导入该依赖,如下所示:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
</dependency>

但实际上我们无需手动导入该起步依赖,因为几乎每一个起步依赖(比如:spring-boot-starterspring-boot-starter-web...)都内置了 spring-boot-starter-logging

因此,当我们使用起步依赖创建 Spring Boot 项目时,日志功能开箱即可用。
且日记框架内部默认实现采用 Logback。

日志内容简介

  • 日志格式:默认情况下,当我们运行程序时,控制台会输出如下日志信息:

    Spring Boot logging

    日志格式默认涵盖 7 个字段,分别为:

    • 日期和时间:精确到毫秒且易于排序。。
    • 日志级别(Log Level):总共包含 5 种日志级别:ERRORWARNINFODEBUGTRACE
      :日志级别具体排序(由低到高)如下:TRACE < DEBUG < INFO < WARN < ERROR < FATAL。且默认的日志输出级别为 INFO,低于 INFO 级别的日志信息不会输出,也即此时就只会输出 INFOWARNERRORFATAL 信息,而不会输出 TRACEDEBUG 日志信息。
    • 进程 ID
    • 分隔符(---):标识真实日志的起始位置。
    • 线程名:方括号([])内部的内容(控制台输出可能会被截断)。
    • 日志记录者:通常为日志打印的源码类名(类名通常会被进行缩略/简写)。
    • 日志具体信息

基础用法

  • 日志打印:在项目中具体使用日志进行打印的方法如下:

    @RestController
    @RequestMapping("logging")
    public class LogController {
    
        private Logger logger = LoggerFactory.getLogger(this.getClass());
    
        @GetMapping("/")
        public String index() {
            logger.trace("A TRACE Message");
            logger.debug("A DEBUG Message");
            logger.info("An INFO Message");
            logger.warn("A WARN Message");
            logger.error("An ERROR Message");
            
            return "logging page";
        }
    }
    

    :Logback 没有 FATAL 级别,它被映射到 ERROR 级别。

    此时运行项目,然后请求curl localhost:8080/logging/,可以在控制台观察到如下日志信息:

    logger

    前文已经讲过,Spring Boot 默认使用的日志级别为 INFO,因此 TRACEDEBUG 日志信息不会得到输出。

    而如果想输出其他级别的日志,就需要更改日志级别,其方法有很多,比如:

    • 输出 DEBUG 日志:只需启动 DEBUG 模式,启动方法有如下几种方法:

      1. 使用 --debug 标识:启动项目时,加入该标识即可:

        # SpringBootDemos-1.0-SNAPSHOT.jar 是项目生成对应的 jar 包
        $ java -jar target/SpringBootDemos-1.0-SNAPSHOT.jar --debug
        

        :生成可执行 jar 包的方法可查看 附录

      2. 配置文件:在application.properties配置文件中启动 DEBUG 模式

        debug=true
        

      :使能 DEBUG 模式 就可以在控制台中看到 DEBUG 级别日志信息,但是自己的应用并未配置为 DEBUG 模式,也就是说即使使能了 DEBUG 模式,自己应用内输出的 DEBUG 信息还是不会打印到控制台。如果想让应用也能输出 DEBUG 日志,可以通过配置logging.level.root=debug...

  • 输出 TRACE 日志:使用--trace标识或者配置文件中配置trace=true

  • 项目日志级别更改:通过在配置文件中配置如下内容:

    # 项目的日志级别设置为 WARN(根 logger)
    logging.level.root=warn
    
    # org.springframework.web 包日志级别(包 looger)
    logging.level.org.springframework.web=debug
    
    # com.yn 包日志级别(此时项目该包下的所有日志就都会打印输出)
    logging.level.com.yn=trace
    
  • 使用日志配置文件:可以通过在classpath路径下提供一个自定义的日志配置文件logback-spring.xml,对日志级别进行设置,如下所示:

    <!-- resources/logback-spring.xml -->
    <logger name="org.springframework" level="INFO" />
    <logger name="com.yn" level="INFO" />
    

    更多具体配置内容,请参考下文:自定义日志配置:Logback 配置文件

还有其他一些设置日志级别的方法,这里就不展开阐述了。
更多内容可参考:Log Levelszero-configuration-logging

  • 简化调用:实际开发中,我们还可以使用 Lombok 来简化日志记录,如下代码所示:

    @RestController
    @RequestMapping("logging")
    @Slf4j // 其他还有:@Log @CommonsLog @Log4j @Log4j2 @XSlf4j
    public class LogController {
    
    //    private Logger logger = LoggerFactory.getLogger(this.getClass());
    
        @GetMapping("/")
        public String index() {
    //        @Slf4j 会自动注入一个名为 log 的日志记录实例
            log.trace("A TRACE Message");
            log.debug("A DEBUG Message");
            log.info("An INFO Message");
            log.warn("A WARN Message");
            log.error("An ERROR Message");
    
            return "logging page";
        }
    }
    

    SLF4J 表示:Simple Logging Facade For Java。它是对所有 Java 的日志记录框架的一个门面装饰,定义了统一的日志抽象接口。

  • 生成日志文件:默认情况下,Spring Boot 只会将日志输出到控制台中,不会写入到文件。但我们可以通过配置logging.file.namelogging.file.path开启日志文件记录功能:

    # application.properties
    # 设置日志文件路径(默认生成的日志文件名为:spring.log)
    logging.file.path=/var/log
    
    # 设置日志文件名
    # 相对路径
    logging.file.name=my.log
    # 绝对路径
    logging.file.name=/var/log/my.log
    

    logging.file.pathlogging.file.name如果同时进行配置,则只有logging.file.name生效。

    日志文件每达到 10 MB 就会发生滚动,重新生成一个新的日志文件。日志文件的切割尺寸可通过logging.file.max-size进行设置。

    # 设置日志文件大小
    logging.file.max-size=10MB
    

    默认情况下,Spring Boot 只会保留最近 7 天内生成的日志文件,可通过logging.file.max-history配置日志保留时间。

    # 日志保留时间
    logging.file.max-history=10
    

    日志归档文件总大小可通过属性logging.file.total-size-cap进行设置,当日志归档超过设置的阈值时,备份的日志会被删除。

    在应用每次启动时,如果想强制清理日志归档文件,可以通过配置logging.file.clean-history-on-start属性。

自定义日志配置:Logback 配置文件

Spring Boot 支持多种不同的日志系统实现,可以通过导入相应的依赖库从而在运行时激活对应的日志系统,并且可以通过在classpathlogging.config属性指定一个配置文件,实现自定义系统日志配置。

对于不同的日志系统,Spring Boot 会默认加载的日志配置文件如下表所示:

Logging System Customization
Logback logback-spring.xmllogback-spring.groovylogback.xmllogback.groovy
Log4j2 log4j2-spring.xmllog4j2.xml
JDK (Java Util Logging) logging.properties

:Spring Boot 建议我们使用带有-spring后缀的作为日志配置文件名称(即相较于使用logback.xml,更建议使用logback-spring.xml)。
如果使用标准配置路径,Spring 无法完全控制日志初始化过程(因为logback.xml的加载时间非常早,导致一些扩展功能无法在其内进行配置,而此时使用logback-spring.xml 即可解决这个问题)。

我们主要关注的是 Logback 的配置文件内容。

要对 Logback 添加配置文件,只需创建resources/logback-spring.xml,然后对该文件进行配置即可,其基本配置内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">

    <contextName>logback</contextName>

    <!-- 创建一个属性/变量-->
    <property name="LOGS" value="./logs"/>

    <!-- 控制台输出配置 -->
    <appender name="Console"
              class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>
                %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable
            </Pattern>
        </layout>
    </appender>

    <!-- 输出到文件 -->
    <appender name="RollingFile"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOGS}/spring-boot-logger.log</file>
        <encoder
                class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
        </encoder>

        <rollingPolicy
                class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- rollover daily and when the file reaches 10 MegaBytes -->
            <fileNamePattern>${LOGS}/archived/spring-boot-logger-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>

    <!-- 根logger,项目日志配置 -->
    <root level="info">
        <appender-ref ref="RollingFile"/>
        <appender-ref ref="Console"/>
    </root>

    <!-- 为包 com.yn 创建一个日志实例 -->
    <logger name="com.yn" level="trace" additivity="false">
        <appender-ref ref="RollingFile"/>
        <appender-ref ref="Console"/>
    </logger>

</configuration>

:日志配置文件路径也可以在application.properties中进行指定:

logging.config=classpath:logback-spring.xml

简单对上述 logback-spring.xml 的配置内容进行一些介绍:

  • <configuration>:配置文件起始块标签,其内我们配置了以下 3 个属性:

    • scan:默认值为true,表示当日志配置文件发生改变时,重新加载该文件。
    • scanPeriod:检测日志配置文件是否被更改的时间间隔。默认时间单位为毫秒,默认扫描间隔为 1 分钟。
      scanPeriod属性只有在scan=true时,才会生效。
    • debug:当此属性设为true时,则会打印 logback 内部日志信息,实时显示 logback 运行状态。该属性默认值为false
  • <contextName>:该标签用于为 logger 实例设置上下文名称。其默认值为default。可以通过%contextName来打印日志上下文名称。
    :可以通过<contextName>来对不同的应用设置各自的名称,这样就可以在同一个日志文件中区分不同应用的日志信息。

  • <property>:该标签用于创建一个变量,后续该配置文件可以通过${property.name}方式引用该变量。

  • <<appender>>:该标签用于配置日志输出节点,其有两个属性:nameclass。其中:

    • name:用于设置输出节点名称(可设置任意名称)
    • class:用于指定输出策略。常用的输出到控制台与输出到文件的class如上述配置所示。
  • <root>:该标签用于创建一个根logger,配置项目日志输出级别(相当于属性loging.level.root)。
    其内部通过标签<appender-ref>引用了我们前面创建的日志输出节点配置。

  • <logger>:该标签用于为某个包,或者具体某个类创建一个日志记录实例。
    :其中addtivity表示是否向上级 logger 传递打印信息,默认为true

更多 Logback 配置文件内容,请参考:A Guide To Logback

多环境日志配置

可以通过在日志配置文件中使用标签<springProfile>来创建不同的环境日志配置。

比如,我们可以通过定义生产环境prod,测试环境test和开发环境dev来实现不同的日志输出,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    ...
    <!-- 测试环境+开发环境. 多个使用逗号隔开. -->
    <springProfile name="test,dev">
        <logger name="com.yn.logging" level="debug"/>
    </springProfile>

    <!-- 生产环境. -->
    <springProfile name="prod">
        <root level="info">
            <appender-ref ref="RollingFile"/>
            <appender-ref ref="Console"/>
        </root>
        <logger name="com.yn.logging" level="ERROR"/>
    </springProfile>

</configuration>

然后,启动服务的时候,设置相应环境的 profile 即可。
比如,可以直接通过命令指定运行环境 profile,如下:

# 运行在开发环境
$ java -jar xxx.jar --spring.profiles.active=dev

Spring Boot 多环境配置内容,可参考:Spring Boot - 多环境配置

其他

  • Spring 环境变量获取:在 Logback 日志配置文件中,可以通过标签<springProperty>来获取 Spring 环境变量(即application.properties中定义的属性),如下所示:

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

    <springProperty>标签功能类似于 Logback 的标注标签<property>,但是它有 4 个属性,分别如下:

    • name:变量名
    • scope:指定变量存储环境上下文(默认为local
    • source:指定要获取的 Spring 环境属性名
    • defaultValue:如果获取不到属性,使用该默认值
  • 日志颜色控制:如果你的终端支持 ANSI,那么可以通过设置颜色文字增加可读性。

    可以通过配置spring.output.ansi.enabled属性来覆盖默认的自动检测,其可选值如下所示:

    # application.properties
    # 开启颜色输出
    spring.output.ansi.enabled=always
    # 自动检测开启颜色输出
    spring.output.ansi.enabled=detect
    # 关闭颜色输出
    spring.output.ansi.enabled=never
    

    如果终端支持 ANSI,则可以通过%clr来配置文字颜色。

    最简单的配置方式如下:

    %clr(%5p)
    

    此时不同的日志级别会默认采用不同的颜色进行区分,具体如下表所示:

    Level Color
    FATAL 红色
    ERROR 红色
    WARN 黄色
    INFO 绿色
    DEBUG 绿色
    TRACE 绿色
当然,我们也可以对不同的日志级别设置别的颜色,支持设置的颜色有如下可选值:
- `blue`
- `cyan`
- `faint`
- `green`
- `magenta`
- `red`
- `yellow`

比如,将日期文字设置为黄色,其配置如下:

```
%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}
```
  • 日志分组:应用中可能存在多个相关的日志实例(logger),那么此时通过 日志分组 功能就可以同时对这些日志实例进行配置。

    比如,如果我们想更改所有 Tomcat 相关日志配置,那么就可以通过将其打包进一个日志组中,如下所示:

    # application.properties
    # tomcat 日志组
    logging.group.tomcat=org.apache.catalina, org.apache.coyote, org.apache.tomcat
    

    然后对该组进行配置即可,比如,更改 tomcat 组的日志级别:

    logging.level.tomcat=TRACE
    

    Spring Boot 默认预置了以下几个日志组,可以直接使用,如下表所示:

    Name Loggers
    web org.springframework.core.codecorg.springframework.httporg.springframework.weborg.springframework.boot.actuate.endpoint.weborg.springframework.boot.web.servlet.ServletContextInitializerBeans
    sql org.springframework.jdbc.coreorg.hibernate.SQLorg.jooq.tools.LoggerListener

附录

  • Lombok 安装:步骤如下:

    1. 首先导入 Lombok 依赖:

      <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <version>1.18.12</version>
          <scope>provided</scope>
      </dependency>
      
    2. 接着为 idea 安装 Lombok 插件,消除代码错误显示:File - Settings - Plugins - 搜索 Lombok - install,安装完成后重启即可。

    3. 开启 annotation processing:File - Settings - Build,Execution,Deployment - Compiler - Annotation Processors,右侧勾选 Enable annotation processing,最后点击 OK 完成配置。

  • 生成可执行 jar 包:在pom.xml中做如下配置:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    

    然后执行:mvn clean package打包生成可执行 jar 包。

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270