摘要
本篇文章详细介绍了SpringBoot 日志管理相关的内容,文章主要参考官网文章的描述内容,并在其基础上进行一定的总结和拓展,以方便学习Spring Boot 的小伙伴能快速掌握Spring Boot 日志管理相关的内容。
日志实现方式
Sping Boot 的日志管理框架采用的是Apache Commons Logging,是Apache软件基金会下的一个开源的日志门面框架。日志门面框架并不直接实现日志的具体功能,而是为不同的日志实现框架提供统一的接口。Spring Boot 为Java.Util.Logging、Log4j2和Logback提供了默认配置,在每种配置情况下,记录器都预先配置为使用控制台输出,也可选择文件输出。
默认情况下,如果你使用的是Spring Boot的 Starters启动,则会使用 Logback 进行日志记录。Spring Boot 会配置适当的Logback 路由,以确保其他日志框架如 Java Util Logging、Commons Logging、Log4J 的依赖库均能正常工作。
Spring Boot 默认日志格式
Spring Boot 的默认日志格式包含如下内容:
-
日期和时间:精确到毫秒,便于排序。
-
日志级别:包括 ERROR、WARN、INFO、DEBUG 或 TRACE。
-
进程 ID。
-
一个 "---" 分隔符,用于区分实际日志消息的开始。
-
应用程序名称:用方括号括起来(默认情况下,仅当设置了 spring.application.name 时才记录)
-
应用程序组:用方括号括起来(默认情况下,仅当设置了 spring.application.group 时才记录)
-
线程名称:用方括号括起来(在控制台输出中可能会被截断)。
-
关联 ID:如果启用了跟踪(上述示例中未显示)
-
记录器名称:通常是源类名(经常被缩写)。
-
日志消息。
Spring Boot 日志配置
日志级别
Spring Boot 支持以下日志级别:
-
ERROR(错误):该级别用于记录系统中发生的严重错误事件,这些错误会导致系统无法正常运行或部分功能失效,通常需要立即关注和处理。
-
WARN(警告):表示系统中出现了一些可能会导致问题的情况,但当前系统仍能继续运行。这些情况虽然不会立即影响系统的正常功能,但需要引起注意,因为它们可能是潜在问题的征兆。
-
INFO(信息):用于记录系统运行过程中的一些重要信息,这些信息可以帮助开发者和运维人员了解系统的基本运行状态和关键操作的执行情况。
-
DEBUG(调试):主要用于开发和调试阶段,记录系统运行过程中的详细信息,帮助开发者定位和解决问题。这些信息通常包含变量的值、方法的调用顺序、程序的执行路径等。
-
TRACE(跟踪):这是最详细的日志级别,用于记录系统运行过程中的每一个细节,包括方法的进入和退出、变量的微小变化等。它提供了比 DEBUG 级别更精细的信息。
-
FATAL: 是所有日志级别中最为严重的一级。当系统记录 FATAL 级别的日志时,意味着系统遭遇到了几乎无法恢复的灾难性错误,整个系统或者关键业务功能已经完全崩溃,无法继续提供正常服务。
-
Logback 没有 FATAL级别,它会将FATAL 映射到ERROR。
-
日志级别默认的颜色配置
如果您的终端支持ANSI,则使用彩色输出来提高可读性。以下是日志级别默认的颜色配置列表:
等级 | 颜色 |
---|---|
| 红色的 |
| 红色的 |
| 黄色的 |
| 绿色的 |
| 绿色的 |
| 绿色的 |
日志级别启动配置
Spring Boot 的日志默认会回显到控制台,并会记录日志级别是 ERROR、WARN、INFO level的日志。
-
启动debug日志
-
$ java -jar myapp.jar --debug 在启动应用程序的时候使用 --debug 标志
-
在application.properties配置文件中配置 debug=true
-
-
启动trace日志
-
$ java -jar myapp.jar --trace 在启动应用程序的时候使用 --trace 标志
-
在application.properties配置文件中配置 trace=true
-
配置某个模块的日志级别
我们可以使用 logging.level.<logger-name>=<level> 语法,配置某个模块的日志级别。以下是一些配置示例:
logging.level.root=warn # 配置根日志记录器的日志级别
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error
文件输出配置
-
logging.file.name:
-
属性用于指定日志文件的完整名称和路径,它会精确地定义日志文件在文件系统中的存储位置和文件名。当你设置了这个属性后,Spring Boot 会将日志信息输出到该指定的文件中。
-
logging.file.name=/var/log/myapp.log
-
这会让 Spring Boot 把日志信息输出到
/var/log
目录下名为myapp.log
的文件中。如果指定的目录不存在,Spring Boot 不会自动创建该目录,而是会抛出异常。
-
-
logging.file.path:
-
属性用于指定日志文件的存储目录,Spring Boot 会在该目录下生成默认名为
spring.log
的日志文件。使用这个属性时,你只需关注日志文件的存储位置,而无需指定具体的文件名。 -
logging.file.path=/var/log/myapp
-
这会让 Spring Boot 在
/var/log/myapp
目录下创建spring.log
文件,并将日志信息写入该文件。如果指定的目录不存在,Spring Boot 会自动创建该目录。
-
-
配置优先级:如果同时配置了
logging.file.name
和logging.file.path
,logging.file.name
的优先级更高,Spring Boot 会按照logging.file.name
指定的路径和文件名生成日志文件,而忽略logging.file.path
的设置。
文件轮换规则配置(仅限Logback)
- 默认日志文件轮换:Spring Boot的默认日志文件记录大小是10MB
- 对于Logback 日志框架,Spring Boot 提供了一些可用于微调的文件日志轮换配置。而对于其他日志系统,则需要在配置文件中自行配置日志轮换规则。以下是关于Spring Boot文件轮换规则的配置列表:
-
属性
描述
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)。
日志分组
-
在 Spring Boot 中,将相关的日志记录器分组,以便同时对它们进行配置是很有用的。例如,你可能经常需要更改所有与 Tomcat 相关的日志记录器的日志级别,但又难以记住顶级包名。
-
为解决这个问题,Spring Boot 允许在 Spring 环境中定义日志组。例如,可在
application.properties
中添加如下内容来定义一个名为 “tomcat” 的日志组:
logging.group.tomcat=org.apache.catalina,org.apache.coyote,org.apache.tomcat
-
定义好日志组后,只需一行配置就能更改该组中所有日志记录器的日志级别,示例如下:
logging.level.tomcat=trace
-
此外,Spring Boot 还包含一些预定义的日志组,可直接使用,具体如下:
名称 | 包含的日志记录器 |
---|---|
web |
|
sql |
|
自定义日志配置
-
激活与自定义方式:不同日志系统可通过在类路径包含相应库来激活,还能在类路径根目录提供合适配置文件,或通过
logging.config
属性指定配置文件位置来进一步自定义。-
logging: config: classpath:custom-logback
-
然后在
src/main/resources
目录下创建custom-logback.xml
文件
-
-
强制指定日志系统:可使用
org.springframework.boot.logging.LoggingSystem
系统属性强制 Spring Boot 使用特定日志系统,值为LoggingSystem
实现类的全限定名,设置为none
可完全禁用 Spring Boot 的日志配置。-
import org.springframework.boot.Banner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication public class CustomLoggingSystemApplication { public static void main(String[] args) { // 强制指定使用 Log4j2 日志系统 System.setProperty("org.springframework.boot.logging.LoggingSystem", "org.springframework.boot.logging.log4j2.Log4j2LoggingSystem"); // 禁用 Spring Boot 的日志配置 // System.setProperty("org.springframework.boot.logging.LoggingSystem", "none"); new SpringApplicationBuilder(CustomLoggingSystemApplication.class) .bannerMode(Banner.Mode.OFF) .run(args); } }
-
-
配置限制:由于日志在
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 无法完全控制日志初始化,且运行 “可执行 jar” 时 Java Util Logging 存在类加载问题,建议尽量避免。
环境属性与系统属性映射
Spring 环境中的一些属性会被转移到系统属性,供日志系统配置使用。以下是环境属性映射到系统属性的列表:
Spring 环境属性 | 系统属性 | 评论 |
---|---|---|
|
| 记录异常时使用的转换字。 |
|
| 如果定义了,则在默认日志配置中使用它。 |
|
| 如果定义了,则在默认日志配置中使用它。 |
|
| 控制台 (stdout) 上使用的日志模式。 |
|
| 日志日期格式的附加器模式。 |
|
| 用于控制台日志记录的字符集。 |
|
| 用于控制台日志记录的日志级别阈值。 |
|
| 文件中使用的日志模式(如果 |
|
| 用于文件记录的字符集(如果 |
|
| 用于文件日志记录的日志级别阈值。 |
|
| 呈现日志级别时使用的格式(默认 |
|
| 用于控制台日志记录的结构化日志记录格式。 |
|
| 用于文件日志记录的结构化日志记录格式。 |
|
| 当前进程 ID(如果可能并且尚未定义为操作系统环境变量则发现)。 |
如果您使用 Logback,以下属性也会被转移:
Spring 环境属性 | 系统属性 | 评论 |
---|---|---|
|
| 滚动日志文件名的模式(默认 |
|
| 是否在启动时清理存档日志文件。 |
|
| 最大日志文件大小。 |
|
| 要保留的日志备份的总大小。 |
|
| 要保留的最大存档日志文件数。 |
其它配置
不为日志配置spring.application.name
logging.include-application-name=
false
不为日志配置spring.application.group
logging.include-application-group=
false
结构化日志
-
结构化日志是一种将日志输出以明确定义、通常为机器可读的格式进行记录的技术。
-
Spring Boot 原生支持以下几种 JSON 格式的结构化日志:
-
Elastic Common Schema (ECS):一种通用的、标准化的日志数据结构,便于在 Elastic Stack 中进行统一的日志分析和处理。
-
Graylog Extended Log Format (GELF):Graylog 日志管理系统所使用的扩展日志格式,能高效地传输和存储日志数据。
-
Logstash:一个开源的数据收集引擎,可对日志进行收集、过滤和转换。
-
启用结构化日志的方法
可通过设置以下属性来启用结构化日志:
-
logging.structured.format.console
:用于控制台输出,将其设置为所需格式的标识符。 -
logging.structured.format.file
:用于文件输出,同样设置为所需格式的标识符
自定义日志配置时的处理
如果使用自定义日志配置,需要更新配置以遵循 CONSOLE_LOG_STRUCTURED_FORMAT
和 FILE_LOG_STRUCTURED_FORMAT
系统属性。以 CONSOLE_LOG_STRUCTURED_FORMAT
为例,在 Logback 和 Log4j2 中,需要将编码器替换为 StructuredLogEncoder
,示例配置如下:
<encoder class="org.springframework.boot.logging.logback.StructuredLogEncoder">
<format>${CONSOLE_LOG_STRUCTURED_FORMAT}</format>
<charset>${CONSOLE_LOG_CHARSET}</charset>
</encoder>
参考默认配置
可以参考 Spring Boot 中包含的默认配置,如:
- Logback Structured Console Appender:Logback 的结构化控制台输出附加器配置。
<?xml version="1.0" encoding="UTF-8"?>
<!--
Console appender with structured logging logback configuration provided for import,
equivalent to the programmatic initialization performed by Boot
--><included>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${CONSOLE_LOG_THRESHOLD}</level>
</filter>
<encoder class="org.springframework.boot.logging.logback.StructuredLogEncoder">
<format>${CONSOLE_LOG_STRUCTURED_FORMAT}</format>
<charset>${CONSOLE_LOG_CHARSET}</charset>
</encoder>
</appender>
</included>
- Logback Structured File Appender:Logback 的结构化文件输出附加器配置。
<?xml version="1.0" encoding="UTF-8"?>
<!--
File appender with structured logging logback configuration provided for import,
equivalent to the programmatic initialization performed by Boot
--><included>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${FILE_LOG_THRESHOLD}</level>
</filter>
<encoder class="org.springframework.boot.logging.logback.StructuredLogEncoder">
<format>${FILE_LOG_STRUCTURED_FORMAT}</format>
<charset>${FILE_LOG_CHARSET}</charset>
</encoder>
<file>${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}</fileNamePattern>
<cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
<maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
<totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
<maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-7}</maxHistory>
</rollingPolicy>
</appender>
</included>
弹性通用模式(ECS)
-
ECS 格式简介:Elastic Common Schema 是一种基于 JSON 的日志记录格式。
-
启用 ECS 格式:在配置文件(如
application.properties
或application.yml
)中,将logging.structured.format.console
和logging.structured.format.file
属性设置为ecs
,即可启用该日志格式。
logging.structured.format.console=ecs
logging.structured.format.file=ecs
-
日志示例:启用 ECS 格式后,日志行呈现为 JSON 对象,包含时间戳、日志级别、进程 ID、线程名、服务名、日志记录器、消息内容和 ECS 版本等信息。
{"@timestamp":"2024-01-01T10:15:00.067462556Z","log.level":"INFO","process.pid":39599,"process.thread.name":"main","service.name":"simple","log.logger":"org.example.Application","message":"No active profile set, falling back to 1 default profile: \"default\"","ecs.version":"8.11"}
-
数据添加方法:这种格式会将 MDC(Mapped Diagnostic Context)中的每个键值对添加到 JSON 对象中。此外,还能使用 SLF4J 流式日志记录 API 的
addKeyValue
方法,向记录的 JSON 对象添加键值对。 -
服务属性自定义:可使用
logging.structured.ecs.service
相关属性对服务值进行自定义,如服务名、版本、环境和节点名等。若未指定服务名和版本,将分别默认使用spring.application.name
和spring.application.version
。
logging.structured.ecs.service.name=MyService
logging.structured.ecs.service.version=1 logging.structured.ecs.service.environment=Production logging.structured.ecs.service.node-name=Primary
Graylog 拓展日志格式(GELF)
-
GELF 格式定义:Graylog 扩展日志格式(GELF)是一种基于 JSON 的日志记录格式,专为 Graylog 日志分析平台设计。
-
启用 GELF 格式:在配置文件(如
application.properties
或application.yml
)中,将logging.structured.format.console
和logging.structured.format.file
属性设置为gelf
,即可启用该日志格式。
logging.structured.format.console=gelf
logging.structured.format.file=gelf
-
日志示例:启用 GELF 格式后,日志行呈现为 JSON 对象,包含版本、短消息、时间戳、日志级别、进程 ID、线程名和日志记录器等信息。
{"version":"1.1","short_message":"No active profile set, falling back to 1 default profile: \"default\"","timestamp":1725958035.857,"level":6,"_level_name":"INFO","_process_pid":47649,"_process_thread_name":"main","_log_logger":"org.example.Application"}
-
数据添加方法:这种格式会将 MDC(Mapped Diagnostic Context)中的每个键值对添加到 JSON 对象中。此外,还能使用 SLF4J 流式日志记录 API 的
addKeyValue
方法,向记录的 JSON 对象添加键值对。 -
字段自定义:可使用
logging.structured.gelf
相关属性对部分字段进行自定义,如主机名和服务版本。若未指定主机名和服务版本,将分别默认使用spring.application.name
和spring.application.version
。
logging.structured.gelf.host=MyService
logging.structured.gelf.service.version=1
Logstash JSON 格式
-
格式定义:Logstash JSON 格式是一种基于 JSON 的日志记录格式。
-
启用方式:在配置文件中,可通过设置
logging.structured.format.console=logstash
和logging.structured.format.file=logstash
来分别启用控制台和文件输出的 Logstash JSON 日志格式。
logging.structured.format.console=logstash
logging.structured.format.file=logstash
-
日志示例
{"@timestamp":"2024-01-01T10:15:00.111037681+02:00","@version":"1","message":"No active profile set, falling back to 1 default profile: \"default\"","logger_name":"org.example.Application","thread_name":"main","level":"INFO","level_value":20000}
-
数据添加:MDC 键值对:该格式会将 MDC(Mapped Diagnostic Context)中包含的每个键值对添加到 JSON 对象中。还能使用 SLF4J 流式日志记录 API 的
addKeyValue
方法,向记录的 JSON 对象添加键值对。 -
标记处理:若添加了标记(markers),这些标记会以字符串数组的形式出现在 JSON 的
tags
字段中。
自定义结构化日志
-
Spring Boot 会为结构化日志的 JSON 名称和值选择合理的默认设置,但有时用户可能需要根据自身需求对 JSON 进行微调,比如更改某些名称以匹配日志摄入系统的要求,或者过滤掉一些无用的成员。
-
常用自定义属性及功能
属性 | 描述 |
---|---|
| 用于过滤 JSON 中的特定路径,排除或包含指定内容 |
| 对 JSON 中的特定成员进行重命名 |
| 向 JSON 中添加额外的成员 |
-
配置示例:可以通过如下配置排除
log.level
,将process.id
重命名为procid
,并添加一个固定的corpname
字段:
logging.structured.json.exclude=log.level
logging.structured.json.rename.process.id=procid
logging.structured.json.add.corpname=mycorp
-
高级自定义方式:对于更高级的自定义需求,用户可以编写实现
StructuredLoggingJsonMembersCustomizer
接口的类,并通过logging.structured.json.customizer
属性声明该类。此外,也可以在META - INF/spring.factories
文件中列出这些实现类来完成声明。
其它结构化日志的支持
-
Spring Boot 的结构化日志支持具有扩展性,允许用户定义自己的自定义格式。实现方式为实现
StructuredLogFormatter
接口,不过要注意,使用 Logback 时泛型类型参数需为ILoggingEvent
,使用 Log4j2 时则为LogEvent
,这意味着实现会与特定的日志系统绑定。 -
示例代码:
class MyCustomFormat implements StructuredLogFormatter<ILoggingEvent> {
@Override
public String format(ILoggingEvent event) {
return "time=" + event.getInstant() + " level=" + event.getLevel() + " message=" + event.getMessage() + "\n";
}
}
-
启用自定义格式:要启用自定义格式,需将
logging.structured.format.console
或logging.structured.format.file
属性设置为自定义实现类的全限定类名。 -
构造参数注入:自定义实现类可以使用构造参数,这些参数会被自动注入,更多详细信息可查看 StructuredLogFormatter 的 JavaDoc。
Logback拓展
-
文件选择:标准的
logback.xml
配置文件加载过早,无法使用这些扩展,需要使用logback-spring.xml
或者通过定义logging.config
属性来指定配置文件。 -
配置扫描限制:这些扩展不能与 Logback 的配置扫描功能一起使用。
特定环境配置(<springProfile>
标签)
-
功能:
<springProfile>
标签允许根据激活的 Spring 配置文件有选择地包含或排除部分配置内容。配置文件相关部分可在<configuration>
元素内的任何位置使用。 -
属性使用:使用
name
属性指定接受该配置的配置文件。name
属性可以是单个配置文件名称(如staging
),也可以是配置文件表达式,配置文件表达式能实现更复杂的配置文件逻辑,例如production & (eu - central | eu - west)
。更多详细信息可查看 Spring Framework 参考指南。 -
示例:
<springProfile name="staging">
<!-- 当 "staging" 配置文件激活时启用的配置 -->
</springProfile>
<springProfile name="dev | staging">
<!-- 当 "dev" 或 "staging" 配置文件激活时启用的配置 -->
</springProfile>
<springProfile name="!production">
<!-- 当 "production" 配置文件未激活时启用的配置 -->
</springProfile>
环境属性配置(<springProperty>
标签)
-
功能:
<springProperty>
标签可将 Spring 环境中的属性暴露出来,以便在 Logback 中使用。若想在 Logback 配置中访问application.properties
文件中的值,该标签会很有用。 -
使用方式:其工作方式与 Logback 的标准
<property>
标签类似,但不是直接指定值,而是指定属性的来源(来自环境)。 -
额外属性:若需要将属性存储在本地作用域之外的地方,可使用
scope
属性;若需要一个备用值(以防环境中未设置该属性),可使用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
),不过可以通过宽松规则将属性添加到环境中。
Log4j2拓展
-
Spring Boot 包含许多 Log4j2 扩展,可帮助进行高级配置。您可以在任何
log4j2-spring.xml
配置文件中使用这些扩展。
特定环境配置(<springProfile>
标签):
-
同Logback特定环境配置介绍内容。
环境属性配置
-
如果您想在 Log4j2 配置中引用 Spring 的属性,则可以使用
spring:前缀查找方法
-
配置示例
<Properties>
<Property name="applicationName">${spring:spring.application.name}</Property> <Property name="applicationGroup">${spring:spring.application.group}</Property> </Properties>
系统属性配置
-
Log4j2 系统属性支持:Log4j2 支持多个系统属性,可用于配置不同的项目。例如,
log4j2.skipJansi
系统属性可用于配置ConsoleAppender
在 Windows 系统上是否尝试使用 Jansi 输出流。
log4j2.skipJansi=false
-
从 Spring 环境获取系统属性:在 Log4j2 初始化之后加载的所有系统属性都可以从 Spring 环境中获取。可以在
application.properties
文件中添加相应的系统属性配置,这样就能借助 Spring 环境来影响 Log4j2 的行为。 -
属性加载优先级:只有当系统属性和操作系统环境变量中不包含要加载的值时,才会考虑 Spring 环境。
-
早期初始化的系统属性限制:在 Log4j2 早期初始化期间加载的系统属性不能引用 Spring 环境,因为这些属性在 Spring 环境可用之前就已被使用。
参考文献
Logging :: Spring Boot