SPRING BOOT 日志

Spring Boot 内部使用 spring-jcl 中的 Mini 版 Apache Commons Logging 接口记录日志,该接口实则是通过 LogAdapter 实现对 SLF4J 的桥接,也就是说 Spring Boot 内部的日志最终还是会通过 SLF4J 来记录。Spring Boot 为 Java Util LoggingLog4J2Logback 提供了默认配置,它们的默认配置都是将日志输出到控制台,并且可以选择将日志输出到文件。

默认情况下,如果使用了起步依赖(Starters),那么将会使用 Logback 作为日志实现。

\[\log_sN\]

日志格式

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
2019-03-05 10:57:51.698  INFO 45469 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2019-03-05 10:57:51.702  INFO 45469 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]

每一行日志,从左往右依次是:

  • 日期和时间:精确至毫秒
  • 日志等级: ERRORWARNINFODEBUGTRACE
  • 进程 ID
  • --- 分隔符,分隔出实际的日志内容
  • 进程名称:以方括号包围
  • 日志名称:通常是日志输出所在类的类名(常用缩写形式)
  • 日志消息

Logback 中没有 FATAL 等级,该等级的日志将会被映射为 ERROR 等级。

输出到控制台

默认的日志配置会在日志消息写入时将消息回显到控制台,且只会记录 ERRORWARNINFO 级别的日志消息。可以在启动应用时通过 --debug 标志开启 "DEBUG" 模式。

$ java -jar myapp.jar --debug

也可以在 application.properties 配置文件中声明 debug true 来开启 "DEBUG" 模式。

开启 DEBUG 模式之后不会影响到应用内部的日志等级,只是将 Spring Boot 内部日志消息等级设置为 DEBUG。这样可以输出更多的 Spring Boot 内部日志消息。

也可以以同样的方式在命令行中通过 --trace 或 application.properties 配置文件中声明 trace=true 来开启 Spring Boot 的 TRACE 模式。结果也是一样的,这个标志只会影响 Spring Boot 内部的日志等级。

日志消息的颜色

在终端支持 ANSI 的时候,以不同颜色标识的日志消息可以使我们更容易阅读。是否开启 ANSI-colored 的日志消息,可以通过属性 spring.output.ansi.enabled 来控制,该属性值有:always,nerver,detect。默认 detect 会尝试输出ANSI-colored 的日志消息。

通过使用 %clr 来配置日志消息的着色,最简单的形式是根据日志的基本来着色,如下所示:

%clr(%5p)

下表是每个日志级别所对应的日志颜色:

日志级别 颜色
FATAL 红色
ERROR 红色
WARN 黄色
INFO 绿色
DEBUG 绿色
TRACE 绿色

此外,还可以自定义日志消息的颜色样式。例如,下面将日志消息中的文本着黄色输出:

%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}

这里支持的颜色样式有: bluecyanfaintgreenmagentaredyellow

输出到文件

默认情况下,Spring Boot 日志消息只会输出到控制台。如果想要在输出到控制台的同时也输出到日志文件中,需要设置 logging.file.namelogging.file.path 属性。

logging.file.name logging.file.path 属性值 描述
(none) (none)   只输出到控制台
指定文件 (none) my.log 输出到指定日志文件,可以是绝对路径或
      当前目录的相对路径
(none) 指定目录 /var/log 输出到指定目录中的 spring.log,
      可以是绝对路径或当前目录的相对路径

日志文件每 10MB 切换一次,并且与输出到控制台一样,默认输出 ERROR、WARN、INFO 级别的日志消息。

Logging properties are independent of the actual logging infrastructure. As a result, specific configuration keys (such as logback.configurationFile for Logback) are not managed by spring Boot.

日志文件切换

如果日志系统的具体实现是 Logback 日志系统,那么可以在 application.propertiesapplication.yaml 中微调日志切换的属性设置。除此之外的其他日志系统中,需要直接配置该系统的配置文件来实现日志配置。比如使用 Log4J2 日志系统,那么就要通过添加 log4j.xml 配置文件来实现日志配置。

Spring Boot 中支持的微调 Logback 文件切换策略的属性有:

属性名 描述
logging.loback.rollingpolicy.file-name-pattern 日志文件名模式
logging.logback.rollingpolicy.clean-history-on-start 是否在应用启动时清理日志归档
logging.logback.rollingpolicy.max-file-size 日志文件大小,标志何时归档日志文件
logging.logback.rollingpolicy.total-size-cap 归档日志大小,标志何时清理归档日志
logging.logback.rollingpolicy.max-history 日志归档保存的天数(默认 7 天)

日志级别

Spring Boot 所支持的所有日志系统的日志级别都以在例如 application.properties 中使用 logging.level.<logger-name>=<level> 属性来设置到 Environment 中,这里 level 可以是 TRACE / DEBUG / INFO / WARN / ERROR / FATAL / OFF 中的任意一个。root logger 可以通过 logging.level.root 属性来设置。

下面是在 application.properties 配置文件中设置日志级别的例子:

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

同样也可以通过环境变量来设置日志级别。比如,~LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB=DEBUG~ 会将 org.springframework.web 设置为 ~DEBUG~。

上述方法只能用于包级别的日志,由于 relaxed binding 总会将环境变量转换为小写,所以不能用这种方式设置类级别的日志。可以通过 SPRING_APPLICATION_JSON 来设置类的日志级别。

TODO: 验证这两种级别的两种方法

日志组

通过日志组可以将一些相关连的日志聚合在一起,以方便同时修改它们。例如,我们可能会要修改一些和 Tomcat 相关连的 logger 的日志级别,但是要记住这些包的名字可能不太容易。

那么在 Spring Boot 中定义包含那些这些不太容易记住包名的与 Tomcat相关连的 logger 的组放在 Spring Environment 中,就可以很方便的在一处来设置它们的日志级别。下面在 application.properties 中定义了解决这个问题的一个 "tomcat" 日志组:

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

这样定义完之后,就可以一次性的修改组中所有 logger 的级别:

logging.level.tomcat=trace

Spring Boot 中预定义了一些开箱即用的日志组:

日志组名 logger
web org.springframework.core.codec,
  org.springframework.http,
  org.springframework.web,
  org.springframework.boot.actuate.endpoint.web,
  org.springframework.boot.web.servlet.ServletContextInitializerBeans
sql org.springframework.jdbc.core,
  org.hibernate.SQL,
  org.jooq.tools.LoggerListener

Using a Log Shutdown Hook

In order to release logging resources it is usually a good idea to stop the logging system when your application terminates. Unfortunately, there's no single way to do this that will work with all application types. If your application has complex context hierarchies or is deployed as a war file, you'll need to investigate the options provided directly by the underlying logging system. For example, Logback offers context selectors which allow each Logger to be created in its own context.

For simple "single jar" applications deployed in their own JVM, you can use the logging.register-shutdown-hook property. Setting logging.register-shutdown-hook to true will register a shutdown hook that will trigger log system cleanup when the JVM exits.

You can set the property in your application.properties or application.yaml file:

logging.register-shutdown-hook=true

自定义日志配置

Spring Boot 会尝试去加载它所支持的日志系统的类文件,那么要使用某个日志系统时,可以直接将它放在 classpath 中。而要再进一步配置日志系统时,可以i将对应日志系统的配置文件放置在 classpath 的根目录下或是通过 Spring Environment 中的 logging.config 属性来指定日志系统的配置文件。

可以使用系统属性 org.springframework.boot.logging.LoggingSystem 来强制 Spring Boot 使用指定的日志系统。该属性的值必须是日志系统实现类的完全限定名,当该属性值为 none 时,Spring Boot 的所有日志配置都将不再有效。

由于日志系统的初始化在 ApplicationContex 创建之间,所以不可能通过 Spring 的 @Configuration 文件中的 @PropertySources 来控制它。只有通过 Java 系统属性才能够去改变或禁用日志系统。

根据应用所选择的日志系统,将会加载下面的配置文件:

日志系统 配置文件
Logback logback-spring.xmllogback-spring.groovylogback.xmllogback.groovy
Log4j2 log4j2-spring.xmllog4j2.xml
JDK (Java Util Logging) logging.properties

Spring Boot 推荐尽可能的使用 -spring 的日志系统配置文件名称,比如 logback-spring.xml 而不是 logback.xml

There are known classloading issues with Java Util Logging that cause problems when running from an 'executable jar'. We recommend that you avoid it when running from an 'executable jar' if at all possible.

为方便自定义配置,一些 Spring Environment 中的属性被复制到了 Java 系统属性中:

Spring Environment Java 系统属性 备注
logging.exception-conversion-word LOG_EXCEPTION_CONVERSION_WORD The conversion word used when
    logging exceptions.
logging.file.name LOG_FILE If defined, it is used in the default log
    configuration.
logging.file.path LOG_PATH If defined, it is used in the default log
    configuration.
logging.pattern.console CONSOLE_LOG_PATTERN The log pattern to use on the console
    (stdout).
logging.pattern.dateformat LOG_DATEFORMAT_PATTERN Appender pattern for log date format.
logging.charset.console CONSOLE_LOG_CHARSET The charset to use for console logging.
logging.pattern.file FILE_LOG_PATTERN The log pattern to use in a file (if
    LOG_FILE is enabled).
logging.charset.file FILE_LOG_CHARSET The charset to use for file logging
    (if LOG_FILE is enabled).
logging.pattern.level LOG_LEVEL_PATTERN The format to use when rendering the
    log level (default %5p).
PID PID The current process ID (discovered if
    possible and when not already defined
    as an OS environment variable).

如果使用的是 Logback 日志系统,下面的这些属性在 Java 系统属性中同样可以使用:

Spring Environment Java 系统属性 备注
logging.logback.rollingpolicy.file-name-pattern LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN 滚动日志文件名的格式
    ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz)
logging.logback.rollingpolicy.clean-history-on-start LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START Whether to clean the archive log files
    on startup.
logging.logback.rollingpolicy.max-file-size LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE Maximum log file size.
logging.logback.rollingpolicy.total-size-cap LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP Total size of log backups to be kept.
logging.logback.rollingpolicy.max-history LOGBACK_ROLLINGPOLICY_MAX_HISTORY Maximum number of archive log files to
    keep.

If you want to use a placeholder in a logging property, you should use Spring Boot's syntax and not the syntax of the underlying framework. Notably, if you use Logback, you should use : as the delimiter between a property name and its default value and not use :-.

You can add MDC and other ad-hoc content to log lines by overriding only the LOG_LEVEL_PATTERN (or logging.pattern.level with Logback). For example, if you use logging.pattern.level=user:%X{user} %5p, then the default log format contains an MDC entry for "user", if it exists, as shown in the following example.

2019-08-30 12:30:04.031 user:someone INFO 22174 --- [  nio-8080-exec-0] demo.Controller
Handling authenticated request

Logback 扩展

Spring Boot 中包含一些用于高级配置的 Logback 扩展,可以在 logback-spring.xml 配置文件中使用它们。

由于标准的 logback.xml 配置文件被加载的时间比较早,所以不能在这个配置文件中使用这些扩展。应该在 logback-spring.xml 中或事 logging.config 属性所指的配置文件中使用这些扩展。

这些扩展不能与 Logback 的配置扫描一起使用。否则将会导致最终的配置出现类似下面的问题:

ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProfile], current ElementPath is [[configuration][springProfile]]

Profile-specific Configuration

The <springProfile> tag lets you optionally include or exclude sections of configuration based on the active Spring profiles. Profile sections are supported anywhere within the <configuration> element. Use the name attribute to specify which profile accepts the configuration. The <springProfile> tag can contain a profile name (for example staging) or a profile expression. A profile expression allows for more complicated profile logic to be expressed, for example production & (eu-central | eu-west). Check the reference guide for more details. The following listing shows three sample profiles:

<springProfile name="staging">
  <!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>

<springProfile name="dev | staging">
  <!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
</springProfile>

<springProfile name="!production">
  <!-- configuration to be enabled when the "production" profile is not active -->
</springProfile>

Environment Properties

<springProperty> 标签会暴露 Spring Environment 中的属性供 Logback 中使用。这样就方便了在 Logback 配置文件中使用 application.properties 配置文件中定义的属性。 <springProperty> 标签的使用与 Logback 的标准 <property> 标签类似。如果要将属性值保存在 local 范围以外的地方,可以使用 <springProperty> 标签的 scope 属性来声明。如果要在 Environment 中没有设置某个属性值的时候给它提供一个默认值,可以使用 <springProperty> 标签的 defaultValue 属性来声明。下面的代码片段中展示了如何暴露属性值到 Logback 中:

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

The source must be specified in kebab case (such as my.property-name). However, properties can be added to the Environment by using the relaxed rules.

Date: 2021-05-10 Mon 13:03:47

Author: xueshumeng

Email: xue.shumeng@yahoo.com

Created: 2023-08-28 Mon 14:16