20220516 Core Features - 4. Logging
前言
Spring Boot 使用 Commons Logging 进行所有内部日志记录,但保持底层日志实现打开。为 Java Util Logging 、Log4J2 和 Logback 提供了默认配置。在每种情况下,记录器都预先配置为使用控制台输出,并且还提供可选的文件输出。
默认情况下,如果您使用 Starters ,则使用 Logback 进行日志记录。还包括适当的 Logback 路由,以确保使用 Java Util Logging、Commons Logging、Log4J 或 SLF4J 的依赖库都能正常工作。
有很多可用于 Java 的日志记录框架。如果上面的列表看起来令人困惑,请不要担心。通常,您不需要更改日志记录依赖项,Spring Boot 默认值就可以正常工作。
当您将应用程序部署到 servlet 容器或应用程序服务器时,使用 Java Util Logging API 执行的日志记录不会路由到应用程序的日志中。这可以防止容器或已部署到它的其他应用程序执行的日志记录出现在应用程序的日志中。
4.1. 日志格式
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: [/*]
输出以下项目:
- 日期和时间:毫秒精度,易于排序
- 日志级别:
ERROR
、WARN
、INFO
、DEBUG
或TRACE
- 进程 ID
- 用于区分实际日志消息开始的分隔符
---
- 线程名称:括在方括号中(可能会被截断以用于控制台输出)
- 记录器名称:这通常是源类名称(通常缩写)
- 日志消息
Logback 没有
FATAL
级别。它被映射到ERROR
4.2. 控制台输出
默认日志配置在消息写入时将消息回显到控制台。默认情况下,将记录 ERROR
,WARN
和 INFO
级别的消息。您还可以通过使用 --debug
标志启动应用程序来启用“调试”模式。
你也可以在
application.properties
中指定debug=true
颜色编码输出
如果您的终端支持 ANSI
,则使用彩色输出来提高可读性。您可以设置 spring.output.ansi.enabled
为 支持的值 以覆盖自动检测。
通过使用 %clr
转换字来配置颜色编码。最简单的转换示例所示:
%clr(%5p)
下表描述了日志级别到颜色的映射:
日志级别 | 颜色 |
---|---|
FATAL |
红色 |
ERROR |
红色 |
WARN |
黄色 |
INFO |
绿色 |
DEBUG |
绿色 |
TRACE |
绿色 |
可以通过将其提供为转换选项来指定应使用的颜色或样式。例如,要使文本变黄,请使用以下设置:
%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}
支持以下颜色和样式:
blue
- 蓝色cyan
- 青色faint
- 浅粉色green
- 绿色magenta
- 品红色red
- 红色yellow
- 黄色
4.3. 文件输出
默认情况下,Spring Boot 仅记录到控制台,不写入日志文件。如果除了控制台输出外还想写日志文件,则需要设置 logging.file.name
或 logging.file.path
属性(例如,在 application.properties
中)。
日志记录属性:
logging.file.name |
logging.file.path |
示例 | 描述 |
---|---|---|---|
(没有) | (没有) | 仅控制台记录。 | |
特定文件 | (没有) | my.log | 写入指定的日志文件。名称可以是确切位置,也可以是相对于当前目录的位置 |
(没有) | 具体目录 | /var/log | 写入指定目录下的 spring.log 。名称可以是确切位置,也可以是相对于当前目录的位置 |
日志文件达到 10 MB时会轮换,并且与控制台输出一样,默认情况下会记录 ERROR
,WARN
和 INFO
消息。
日志记录相关属性独立于实际的日志记录基础设施。因此,特定的配置键(例如
logback.configurationFile
用于 Logback)不由 Spring Boot 管理。
4.4. 文件轮换
如果您使用的是 Logback,则可以使用您的 application.properties
或 application.yaml
文件微调日志轮换设置。对于所有其他日志记录系统,您将需要自己直接配置轮换设置(例如,如果您使用 Log4J2 ,那么您可以添加一个 log4j2.xml
或 log4j2-spring.xml
文件)。
支持以下轮换策略属性:
属性 | 描述 |
---|---|
logging.logback.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 ) |
4.5. 日志级别
所有支持的日志系统可以在 Spring Environment 设置日志级别(例如,通过 application.properties
),通过使用 logging.level.<logger-name>=<level>
,其中 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
以上方法仅适用于程序包级别的日志记录。由于宽松绑定总是将环境变量转换为小写,因此无法以这种方式为单个类配置日志记录。如果需要为类配置日志记录,则可以使用
SPRING_APPLICATION_JSON
变量
4.6. 日志组
能够将相关记录器分组在一起通常很有用,以便可以同时配置它们。例如,您可能通常会更改所有与 Tomcat 相关的记录器的记录级别,但是您不容易记住顶层软件包。
为了解决这个问题,Spring Boot 允许您在 Spring Environment
中定义日志记录组。例如,这是通过将 tomcat
组添加到您的 application.properties
方式来定义它的方法:
logging.group.tomcat=org.apache.catalina, org.apache.coyote, org.apache.tomcat
定义后,您可以使用一行配置更改该组中所有记录器的级别:
logging.level.tomcat=trace
Spring Boot 包括以下可开箱即用的预定义日志记录组:
名称 | Loggers |
---|---|
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 |
4.7. 使用日志关闭挂钩
为了在您的应用程序终止时释放日志资源,提供了一个关闭挂钩,该挂钩将在 JVM 退出时触发日志系统清理。除非您的应用程序部署为 war 文件,否则此关闭挂钩会自动注册。如果您的应用程序具有复杂的上下文层次结构,则关闭挂钩可能无法满足您的需求。如果没有,请禁用关闭挂钩并调查底层日志系统直接提供的选项。例如,Logback 提供 上下文选择器 ,允许每个 Logger 在其自己的上下文中创建。您可以使用 logging.register-shutdown-hook
属性来禁用关闭挂钩。将其设置为 false
将禁用注册。您可以在 application.properties
或 application.yaml
文件中设置属性:
logging.register-shutdown-hook=false
4.8. 自定义日志配置
可以通过在类路径中包含适当的库来激活各种日志记录系统,并可以通过在类路径的根目录或 Spring Environment
属性 logging.config
指定的位置中提供适当的配置文件来进一步自定义各种日志记录系统。
您可以通过使用 org.springframework.boot.logging.LoggingSystem
系统属性来强制 Spring Boot 使用特定的日志系统。该值应该是 LoggingSystem
实现的完全限定的类名。您还可以通过使用值 none
完全禁用 Spring Boot 的日志记录配置。
-Dorg.springframework.boot.logging.LoggingSystem=none
由于日志记录是在
ApplicationContext
创建之前初始化的,因此无法从 Spring@Configuration
文件中的@PropertySources
控制日志记录属性。更改日志记录系统或完全禁用它的唯一方法是通过系统属性。
根据您的日志记录系统,将加载以下文件:
日志系统 | 日志系统配置文件 |
---|---|
Logback | logback-spring.xml logback-spring.groovy logback.xml logback.groovy |
Log4j2 | log4j2-spring.xml log4j2.xml |
JDK (Java Util Logging) | logging.properties |
建议您将
-spring
变体用于日志记录配置(例如,使用logback-spring.xml
而不是logback.xml
)。如果使用标准配置位置,Spring 将无法完全控制日志初始化。
Java Util Logging 存在已知的类加载问题,这些问题在从“可执行 jar”运行时会导致问题。如果可能,我们建议您在从“可执行 jar”运行时避免使用它。
为了帮助进行自定义,一些其他属性从 Spring Environment
转移到 系统属性,如下表所述:
Spring Environment | System Property | 备注 |
---|---|---|
logging.exception-conversion-word |
LOG_EXCEPTION_CONVERSION_WORD |
记录异常时使用的转换字 |
logging.file.name |
LOG_FILE |
如果定义,它将在默认日志配置中使用 |
logging.file.path |
LOG_PATH |
如果定义,它将在默认日志配置中使用 |
logging.pattern.console |
CONSOLE_LOG_PATTERN |
控制台上使用的日志模式(stdout) |
logging.pattern.dateformat |
LOG_DATEFORMAT_PATTERN |
记录日期格式的 Appender 模式 |
logging.charset.console |
CONSOLE_LOG_CHARSET |
用于控制台日志记录的字符集 |
logging.pattern.file |
FILE_LOG_PATTERN |
文件中使用的日志模式(如果 LOG_FILE 已启用) |
logging.charset.file |
FILE_LOG_CHARSET |
用于文件日志记录的字符集(如果 LOG_FILE 已启用) |
logging.pattern.level |
LOG_LEVEL_PATTERN |
呈现日志级别时使用的格式(默认 %5p ) |
PID |
PID |
当前进程 ID (如果可能,并且尚未将其定义为 OS 环境变量时,将被发现) |
如果使用 Logback,还会转移以下属性:
Spring Environment | System Property | 备注 |
---|---|---|
logging.logback.rollingpolicy.file-name-pattern |
LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN |
翻转日志文件名的模式(默认 ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz ) |
logging.file.clean-history-on-start |
LOG_FILE_CLEAN_HISTORY_ON_START |
是否在启动时清除存档日志文件 |
logging.file.max-size |
LOG_FILE_MAX_SIZE |
最大日志文件大小 |
logging.file.total-size-cap |
LOG_FILE_TOTAL_SIZE_CAP |
要保留的日志备份的总大小 |
logging.file.max-history |
LOG_FILE_MAX_HISTORY |
要保留的归档日志文件的最大数量 |
所有受支持的日志记录系统在解析其配置文件时都可以使用系统属性。有关示例,请参见 spring-boot.jar
中的默认配置:
如果要在日志记录属性中使用占位符,则应使用 Spring Boot 的语法 ,而不是底层框架的语法。值得注意的是,如果您使用Logback,则应将
:
用作属性名称与其默认值之间的分隔符,而不应使用:-
您可以通过仅覆盖
LOG_LEVEL_PATTERN
(或使用 Logback 的logging.pattern.level
)将 MDC 和其他临时内容添加到日志行。例如,如果使用logging.pattern.level=user:%X{user} %5p
,则默认日志格式包含user
的MDC条目(如果存在),如以下示例所示2019-08-30 12:30:04.031 user:someone INFO 22174 --- [ nio-8080-exec-0] demo.Controller Handling authenticated request
参考:在SpringBoot项目中添加logback的MDC
4.9. 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]]
4.9.1. 特定于 profile 的配置
使用 <springProfile>
标签,您可以根据激活的 Spring Profiles 选择包括或排除配置部分。 profile 部分在 <configuration>
标签内的任何位置都受支持。使用 name
属性指定哪个 profile 接受配置。<springProfile>
标签可包含一个简单的 profile 的名称(例如staging
)或 profile 表达式。profile 表达式允许表达更复杂的 profile 逻辑,例如 production & (eu-central | eu-west
)。有关更多详细信息,请参阅参考指南。以下清单显示了三个示例 profile :
<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>
4.9.2. Environment 属性
<springProperty>
标签可以让你公开 Spring Environment
属性让 Logback 使用。如果您想从 Logback 配置中访问 application.properties
文件中的值,这样做会很有用。该标签的工作方式类似于 Logback 的标准 <property>
标签。但是,您无需直接指定 value
,而是指定 source
属性(来自 Environment
)。如果需要将属性存储在 local
作用域之外的其他位置,则可以使用 scope
属性。如果需要备用值(以防未在 Environment
中设置属性),则可以使用 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>
...
</appender>
source
属性必须是短横线式语法(例如my.property-name
)。但是,可以使用宽松规则将属性添加到Environment
中。
参考:Spring Boot 日志原理
参考源码:使用 org.springframework.boot.context.logging.LoggingApplicationListener
监听器监听多个事件:
ApplicationStartingEvent.class,
ApplicationEnvironmentPreparedEvent.class,
ApplicationPreparedEvent.class,
ContextClosedEvent.class,
ApplicationFailedEvent.class
在触发 ApplicationStartingEvent
事件时,初始化日志系统,参考 org.springframework.boot.logging.LoggingSystem#get(java.lang.ClassLoader)