跳至主要內容

13. 特性-日志

安图新大约 12 分钟

13. 特性-日志

Spring Boot 日志

简介

Spring Boot 对所有的内部日志使用Commons Logging,但是底层的日志实现是开放的。
提供了Java Util LoggingLog4J2Logback的默认配置。在每种情况下,记录器都被预先配置为使用控制台输出,可选的文件输出也可用。
默认情况下,如果使用spring-boot-starter-logging,则使用Logback(SLF4J)进行日志记录。还包括了适当的Logback路由,以确保使用Java Util LoggingCommons LoggingLog4JSLF4J的依赖库都能正常工作。

Java 有很多可用的日志记录框架。如果上面的列表看起来很混乱,不要担心。通常情况下,你不需要更改日志依赖项,Spring Boot 默认值就可以正常工作。
当你将应用程序部署到Servlet容器或应用程序服务器时,使用Java Util logging API 执行的日志不会被发送到应用程序的日志中。 这可以防止容器执行日志记录或已经部署到它的其他应用程序不会出现在应用程序的日志中。

Java 日志框架详解参考以下文章:
Java 核心技术-日志(上)open in new window
Java 核心技术-日志(下)open in new window

日志格式化

Spring Boot 的默认日志输出类似如下示例:

2022-04-17 21:56:31.290  INFO 13119 --- [           main] c.e.e.ExternalizedConfigApplication      : Starting
2022-04-17 21:56:31.292  INFO 13119 --- [           main] c.e.e.ExternalizedConfigApplication      : No active profile set, falling back to 1 default profile: "default"
2022-04-17 21:56:32.014  INFO 13119 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-04-17 21:56:32.022  INFO 13119 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-04-17 21:56:32.022  INFO 13119 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/10.0.18]

输出项如下:

  • 日期和时间:毫秒精度和容易排序。
  • 日志级别:ERROR、WARN、INFO、DEBUG、TRACE
  • 进程标识
  • 分隔符用于区分实际日志消息的开始
  • 线程名:用方括号括起来(在控制台输出时可能会被截断)。
  • 日志名称:这通常是源类名(通常缩写)。
  • 日志信息

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

控制台输出

默认的日志配置在消息被写入时将消息回显到控制台。缺省情况下,日志级别为 error、warn 和 info。还可以通过使用——debug 标志启动应用程序来启用“debug”模式。
$java -jar myapp.jar --debug

你也可以在你的application.properties中指定debug=true

当启用调试模式时,将选择核心日志记录器(嵌入式容器、Hibernate 和 Spring Boot)配置为输出更多信息。
启用调试模式不会将应用程序配置为使用 debug 级别记录所有消息。

或者,你可以通过使用——trace标志(或者在application.properties中使用trace=true)启动你的应用程序来启用“trace”模式。
这样做可以为选择的核心日志记录器(嵌入式容器、Hibernate 模式生成和整个 Spring 组合)启用跟踪日志记录。

彩色编码输出

如果您的终端支持 ANSI,则使用颜色输出来提高可读性。您可以将spring.output.ansi.enabled设置为一个支持的值(org.springframework.boot.ansi.AnsiOutput.Enabled)。

枚举值描述
DETECT尝试检测ANSI着色功能是否可用(默认值)
ALWAYS启用ANSI
NEVER禁用ANSI

颜色编码是通过使用%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只将日志记录到控制台,不写入日志文件。如果想在控制台输出之外写入日志文件,需要设置logging.file.namelogging.file.path属性(例如,在application.properties中)。

下面列表显示logging.* 属性如何一起使用:

logging.file.namelogging.file.path例子描述
控制台输出
特定文件my.log写入指定的日志文件。名称可以是确切的位置或相对于当前目录。
特定目录/var/logspring.log写入指定目录。名称可以是确切的位置或相对于当前目录。

默认当日志文件达到10M时会归档,重新输出到新文件中,并且与控制台输出一样,默认记录ERROR-level、WARN-level 和INFO-level 消息。

日志属性独立于实际的日志基础设施。因此,特定的配置键(例如Logbacklogback.configurationFile)不被 Spring Boot 管理。

文件归档

如果正在使用Logback,可以在application.propertiesapplication.yaml中对日志归档进行设置。
对于所有其他日志系统,需要自己直接配置归档设置(例如,如果使用Log4J2,则可以添加Log4J2.xmlLog4J2-spring.xml文件)。
支持以下归档属性设置:

NameDescription
logging.logback.rollingpolicy.file-name-pattern用于创建日志归档的文件名方式
logging.logback.rollingpolicy.clean-history-on-start是否应该在应用程序启动时进行日志归档清理。
logging.logback.rollingpolicy.max-file-size归档前日志文件的最大大小(默认10m)
logging.logback.rollingpolicy.total-size-cap在删除日志文件之前,日志文件的最大容量(默认0)
logging.logback.rollingpolicy.max-history保留的归档日志文件的最大数量(默认为7)。

日志级别

所有支持的日志系统都可以在Spring Environment中(例如application.properties)使用logging.level.<logger-name>=<level>设置日志级别,
其中级别为TRACEDEBUGINFOWARNERRORFATALOFF之一。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 变量。

日志组

能够将相关的日志记录分组在一起以便能够同时配置是有时候非常有用的。例如,通常可能会更改所有与Tomcat相关的日志记录的日志级别,但是不容易记住顶级包名。
为了解决这个问题,Spring Boot 允许您在 Spring 环境中定义日志组。例如可以通过将“tomcat”组添加到 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

日志关闭 Hook

为了在应用程序终止时释放日志记录资源,提供了一个关闭钩子,它将在 JVM 退出时触发日志系统清理。除非将应用程序部署为 war 文件,否则此关闭钩子将自动注册。如果应用程序具有复杂的上下文层次结构,那么关闭钩子可能不能满足你的需求。

禁用日志关闭钩子,直接使用底层日志系统提供的选项。例如Logback提供了上下文选择器,允许在自己的上下文中创建每个Logger。可以使logging.register-shutdown-hook属性来禁用关闭钩子,设置为false将禁用注册。你可以在application.propertiesapplication.yaml文件中设置。

#默认true
logging.register-shutdown-hook=false

自定义日志配置

可以通过在classpath中包含适当的库来激活各种日志记录系统,并且可以通过在classpath的根目录或Spring Environment属性指定的位置提供合适的配置文件来进一步定制:logging.config
logging.config=classpath:logback.xml

你可以通过使用org.springframework.boot.logging.LoggingSystem系统属性来强制 Spring Boot 使用特定的日志系统。该值应该是LoggingSystem实现的完全限定类名。还可以使用none值完全禁用 Spring Boot 的日志配置( System.setProperty("org.springframework.boot.logging.LoggingSystem","none"))。

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

不同日志系统加载的配置列表如下:

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

如果可能,建议对日志配置使用-spring方式(例如,logback-spring.xml而不是logback.xml)。如果使用标准配置位置,Spring 不能完全控制日志初始化。

在 Java Util Logging 中有一些已知的类加载问题,当从一个“executable jar”中运行时,会导致问题。建议在从“executable jar”中运行时尽量避免它。

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

Spring EnvironmentSystem PropertyComments
logging.exception-conversion-wordLOG_EXCEPTION_CONVERSION_WORD记录异常时使用的转换词
logging.file.nameLOG_FILE如果定义了,则在默认日志配置中使用
logging.file.pathLOG_PATH如果定义了,则在默认日志配置中使用
logging.pattern.consoleCONSOLE_LOG_PATTERN要在控制台上使用的日志模式(stdout)
logging.pattern.dateformatLOG_DATEFORMAT_PATTERN日志日期格式的Appender模式。
logging.charset.consoleCONSOLE_LOG_CHARSET用于控制台日志记录的字符集
logging.pattern.fileFILE_LOG_PATTERN在文件中使用的日志模式(如果启用了LOG_FILE)
logging.charset.fileFILE_LOG_CHARSET用于文件日志记录的字符集(如果启用了LOG_FILE)
logging.pattern.levelLOG_LEVEL_PATTERN呈现日志级别时使用的格式(默认%5p)
PIDPID当前进程ID

如果使用 Logback,还会转移以下属性:

Spring EnvironmentSystem PropertyComments
logging.logback.rollingpolicy.file-name-patternLOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN滚动日志文件名的模式(默认${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz)
logging.logback.rollingpolicy.clean-history-on-startLOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START是否启动时清理归档日志文件。
logging.logback.rollingpolicy.max-file-sizeLOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE最大日志文件大小
logging.logback.rollingpolicy.total-size-capLOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP要保留的日志备份的总大小。
logging.logback.rollingpolicy.max-historyLOGBACK_ROLLINGPOLICY_MAX_HISTORY归档日志文件的最大数量

所有支持的日志系统在解析其配置文件时都可以查询 System 属性,下列为不同日志系统配置例子:

如果你想在日志属性中使用一个占位符,你应该使用 Spring Boot 的语法,而不是底层框架的语法。值得注意的是,如果使用Logback,应该使用:作为属性名及其默认值之间的分隔符,而不是使用:-。
通过只覆盖LOG_LEVEL_PATTERN,可以将MDC和其他特别内容添加到日志行中(或者Logback使用logging.pattern.level)。例如如果你用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

Logback 扩展

Spring Boot 包含许多Logback扩展,可以帮助进行高级配置。可以在配置文件logback-spring.xml中使用这些扩展。
由于标准的logback.xml配置文件加载得太早不能使用扩展。需要使用logback-spring.xml或自定义logging.config属性。

扩展不能与 Logback 的配置扫描open in new window一起使用,
如果尝试这样做,对配置文件进行更改将导致记录类似以下错误之一的错误:
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 配置

<springProfile>标签根据激活的 Spring profiles 有选择地包含或排除配置部分。 Profile 节点在<configuration>元素中的任何位置都支持,使用name属性指定profile名称。还可以使用复杂的表达式,例如production & (eu-central | eu-west)

<springProfile name="staging">
    <!--这段配置在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 属性

<springProperty> 标签可以从 Spring Environment 获取属性提供给Logback使用,如果希望 application.properties 中的属性可以在Logback配置能使用,这个标签就非常有用了。
这个标签的工作方式跟Logback中的<property>类似。这个标签不能直接指定一个value,而是需要指定一个source(来自Environment)
。如果需要将属性存储在局部作用域以外的其他地方,可以使用scop属性设置作用范围。如果需要一个默认值(如果没有在 Environment 中设置该属性)那么可以使用defaultValue属性设置。

<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 中。

上次编辑于:
贡献者: Andy