Spring Boot日志详解 环球播报

时间:2023-06-07 13:08:45     来源:哔哩哔哩

Spring Boot中的日志抽象确实是SLF4J(Simple Logging Facade for Java),它是一个面向Java的简单日志门面,旨在将各种现有的日志框架映射到基于统一抽象接口的通用API上。

通过使用SLF4J,应用程序可以将日志记录器与任何后端日志实现(如Log4j、Logback、Java Util Logging等)进行解耦。这使得在不更改应用程序代码的情况下,可以轻松地在不同的日志实现之间切换。

而Spring Boot中默认的日志实现是Logback,它是由同一作者创建的log4j框架的改进版。Logback是一个功能强大、快速且易于配置的日志框架,它提供了多种日志输出渠道(包括控制台、文件、远程套接字、可插拔的多种数据库支持等),并支持过滤器、多线程等在内的一系列高级特性。


(资料图)

当然,你也可以在Spring Boot中使用各种不同的日志框架,比如Log4j2、SLF4j等,只需要在项目中引入对应的依赖,按照对应的配置方式即可。

1、日志的抽象与实现

简化的日志调用关系图

2、配置文件

2.1、application.properties:logging.config

在 application.properties 文件中,logging.config 属性用于指定 Logback 配置文件的位置。Logback 是一个流行的 Java 日志框架,它提供了一种灵活的方式来记录应用程序日志。通过在 application.properties 文件中设置 logging.config 属性,您可以指定 Logback 配置文件的位置。例如,如果您的 Logback 配置文件名为 logback-spring.xml,并且位于应用程序的根目录下,则您可以在 application.properties 文件中添加以下行:logging.config=classpath:logback-spring.xml这将告诉 Spring Boot 使用 logback-spring.xml 文件作为 Logback 配置文件。请注意,classpath: 前缀表示该文件位于应用程序的类路径下。如果您没有在 application.properties 文件中设置 logging.config 属性,则 Spring Boot 将使用默认的 Logback 配置。默认情况下,Spring Boot 会在类路径下查找名为 logback-spring.xml 或 logback.xml 的文件,并使用找到的第一个文件作为 Logback 配置文件。如果找不到任何文件,则 Spring Boot 将使用 Logback 的默认配置。通过使用 logging.config 属性,您可以轻松地指定 Logback 配置文件的位置,并自定义应用程序的日志记录行为。在 Spring Boot 中,默认情况下,将使用 Logback 的默认配置。Logback 是一个流行的 Java 日志框架,它提供了一种灵活的方式来记录应用程序日志。如果您没有在应用程序中显式地配置 Logback,则 Spring Boot 将使用 Logback 的默认配置。默认情况下,Logback 的默认配置将日志事件输出到控制台,并将日志级别设置为 INFO。如果您需要更改日志记录行为,则可以在应用程序中配置 Logback,例如通过创建一个名为 logback-spring.xml 的配置文件,并在其中定义附加器、日志记录器和日志级别等元素。请注意,如果您使用的是 Spring Boot,那么 <shutdownHook> 通常不需要显式添加,因为 Spring Boot 会自动注册一个关闭钩子来处理日志记录。但是,在某些情况下,您可能需要手动添加 <shutdownHook> 以确保日志记录在应用程序关闭时能够正常完成。

在Spring Boot中,默认情况下会尝试从以下几个位置加载日志配置:

classpath:logback-spring.xml

classpath:logback-spring.groovy

classpath:logback.xml

classpath:logback.groovy

因此,当您没有在application.properties或application.yml中配置logging.config属性时,Spring Boot会按照默认规则去加载上述配置文件。当然,如果您需要加载的日志配置文件不在默认路径下,或者除了Logback以外的其他日志实现,那么就需要在logging.config属性中显式地指定日志配置文件路径。

需要注意的是,当存在多个日志配置文件时,Spring Boot会优先加载后缀为-spring的配置文件,这是因为Spring-boot-starter-logging依赖中封装了对于Spring的配置的特殊处理,使用该后缀的配置文件可以实现更强的灵活性和扩展性,例如可以引入Spring的属性占位符。

2.2、application.properties与logback-spring.xml的优先级

当在application.properties/application.yml和logback-spring.xml中都配置了同一属性时(比如logging.level.root),Spring Boot会优先读取application.properties/application.yml中的配置,而忽略logback-spring.xml中的配置。

这是因为在Spring Boot的日志系统中,logging属性优先级最高,即使你在 logback-spring.xml中配置了某个属性,如果在 application.properties/application.yml中发现了同名的属性,则会覆盖logback-spring.xml中的配置。这也是Spring Boot日志配置中logging属性优先级高于logback-spring.xml中的原因。

因此,在实际应用中,如果您需要对日志输出级别、使用附加器等进行配置,推荐使用logback-spring.xml这样的日志配置文件,它可以实现更加灵活和细粒度的配置,而application.properties/application.yml中的配置主要用于简洁明了的全局配置。

3、logback-spring.xml标签说明

4、自定义MDC

示例:

这个日志格式中,[,,,]这一部分表示MDC(Mapped Diagnostic Context),它是一种记录应用程序信息的机制,在Logback框架和Spring Cloud Sleuth中都有应用。

MDC机制通常用于在系统运行时,记录一些信息,在日志输出时将这些信息一并输出,帮助我们在分析日志时能够更轻松地定位问题。例如,可以记录请求ID、用户IP、客户端信息等,然后在日志中输出这些信息,方便跟踪和排查。

在Spring Cloud Sleuth中,MDC中一般会包含Trace ID、Span ID,代表当前所在的请求链路信息,用于服务追踪和调用链路追踪。[,,,]这种空的中括号表示当前日志所在的上下文中没有设置MDC信息。

需要注意的是,MDC中记录的信息必须是线程私有的,不同线程之间不能共用MDC。若要在多线程环境下使用MDC,一般会配合使用ThreadLocal等线程安全的工具。

Logback支持自定义MDC信息。可以通过在代码中设置MDC,然后在日志输出时通过%X占位符输出MDC中的数据。比如:

在上面的代码中,我们在MDC中添加了一个名为requestId的键值对,然后在日志记录时使用了%X占位符将requestId的值输出。

在Logback的配置文件中也可以指定每个appender是否包含MDC信息,举个例子:

在上面的配置中,我们使用了%X{requestId}来输出MDC中名为requestId的键的值,将值输出到日志消息的括号中。

需要注意的是,在Logback中设置MDC信息可能会对性能造成影响,过多或过大的MDC数据可能会导致GC times过长等问题。为了避免这些问题,应该尽量精简MDC信息,只记录必要的信息。并且,MDC信息应该在不使用时及时清除。

在Spring Cloud Sleuth中,MDC默认记录Trace ID、Span ID以及Parent Span ID三个值,它们在MDC中用逗号分隔,因此一般情况下,MDC值为3个逗号。

这三个值的具体含义如下:

Trace ID:标识整个请求链路的ID,它能够串联整个请求链路中的所有Span。

Span ID:标识当前Span的ID,以区分一个Trace中包含的不同Span。

Parent Span ID:与Span ID一起使用,标识当前Span的父级Span ID。

这三个值在Spring Cloud Sleuth中都是使用UUID生成的唯一标识符。在日志输出时,可以使用%X{traceId}%X{spanId}%X{parentId}这些占位符输出这些值。

如果你在输出日志时,发现MDC值不是三个逗号,而是其他的分隔符,或者对应的值不是UUID,这可能是因为自己修改了配置导致的,可以查看一下配置文件和相关代码来进行排查。

这个日志格式中的 true表示是否已经记录了正确的MDC值,即Trace ID、Span ID以及Parent Span ID三个值。当为true时,表示MDC中已记录了这三个值,并且这些值可以跨度传播至请求链中的下游调用。如果值为false,则可能意味着MDC没有设置好,或者日志记录器没有正确的配置。

标签:

最新文章推荐