SPRING BOOT 日志
Spring Boot 内部使用 spring-jcl 中的 Mini 版 Apache Commons Logging 接口记录日志,该接口实则是通过 LogAdapter 实现对 SLF4J 的桥接,也就是说 Spring Boot 内部的日志最终还是会通过 SLF4J 来记录。Spring Boot 为 Java Util Logging,Log4J2 和 Logback 提供了默认配置,它们的默认配置都是将日志输出到控制台,并且可以选择将日志输出到文件。
默认情况下,如果使用了起步依赖(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: [/*]
每一行日志,从左往右依次是:
- 日期和时间:精确至毫秒
- 日志等级:
ERROR
、WARN
、INFO
、DEBUG
、TRACE
- 进程 ID
---
分隔符,分隔出实际的日志内容- 进程名称:以方括号包围
- 日志名称:通常是日志输出所在类的类名(常用缩写形式)
- 日志消息
Logback 中没有
FATAL
等级,该等级的日志将会被映射为ERROR
等级。
输出到控制台
默认的日志配置会在日志消息写入时将消息回显到控制台,且只会记录 ERROR
、 WARN
和 INFO
级别的日志消息。可以在启动应用时通过 --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}
这里支持的颜色样式有: blue
、 cyan
、 faint
、 green
、 magenta
、 red
、 yellow
。
输出到文件
默认情况下,Spring Boot 日志消息只会输出到控制台。如果想要在输出到控制台的同时也输出到日志文件中,需要设置 logging.file.name
或 logging.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.properties
或 application.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
(orlogging.pattern.level
with Logback). For example, if you uselogging.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 asmy.property-name
). However, properties can be added to theEnvironment
by using the relaxed rules.