Spring Boot日志详解

目录

1、日志的抽象与实现

2、配置文件

2.1、application.properties

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

3、logback-spring.xml标签说明

4、自定义MDC


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、日志的抽象与实现

SpringBoot选用 SLF4j(日志抽象层)和logback(日志实现)

简化的日志调用关系图

 

2、配置文件

2.1、application.properties

在 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中,默认情况下会尝试从以下几个位置加载日志配置:

  1. classpath:logback-spring.xml

  2. classpath:logback-spring.groovy

  3. classpath:logback.xml

  4. 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标签说明

<?xml version="1.0" encoding="UTF-8"?>
<!--父级标签configuration-->
<configuration>
    <!--"logback-spring.xml"中的<include>元素用于将其他配置文件中的日志配置包含到当前文件中,以便于更好地管理和组织日志信息,它通常被用于避免在多个配置文件之间进行复制和粘贴。使用<include>元素,可以将已经存在的一个或多个日志配置文件中的内容包含在当前文件中,从而避免重复配置和减少代码量。-->
    <!--<include>元素的属性file指定路径或URL,指向要包含的另一个配置文件。例如:可以在logback-spring.xml中使用<include>元素包含日志配置文件"logback-debug.xml":-->
    <!--<configuration>-->
        <!-- 其他配置 -->
        <!--<include file="logback-debug.xml"/>-->
    <!--</configuration>-->
    <!--这样,在logback-spring.xml中就会自动包含"logback-debug.xml"中的所有配置,并结合当前文件的其他配置来生成日志记录信息。这种方式带来了配置的复用性和管理的方便性,同时减少了代码编写的工作量。-->
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <!--"logback-spring.xml"中的<springProperty>元素用于设置Spring属性并在日志配置文件中引用它们。在定义<springProperty>元素后,可以使用 ${属性名} 在配置文件中引用这些属性。通常情况下,在Spring特定的环境中,这些属性可以通过配置文件进行设置,而不需要修改日志配置文件。-->
    <!--以下是一个简单的示例,展示了如何在"logback-spring.xml"中使用<springProperty>元素:-->
    <!--<configuration>-->
        <!--<springProperty scope="context" name="applicationName" source="spring.application.name"/>-->
        <!--<appender name="FILE" class="ch.qos.logback.core.FileAppender">-->
            <!--<file>${applicationName}.log</file>       &lt;!&ndash; 引用在<springProperty>中定义的属性 &ndash;&gt;-->
            <!-- 其他配置 -->
        <!--</appender>-->
    <!--</configuration>-->
    <!--在上面的例子中,使用<springProperty>元素在"logback-spring.xml"定义一个名为"applicationName"的属性,并引用了Spring的"spring.application.name"属性设置了值。在<appender>元素中使用${applicationName}引用了这个属性,从而实现了动态地设置输出的日志文件名。通过使用<springProperty>元素,我们可以在日志配置文件中使用Spring的属性来配置和管理日志信息,从而实现更加灵活和可扩展的日志系统。-->
    <springProperty scope="context" name="springAppName" source="spring.application.name"/>
    <!--logback-spring.xml中的contextName属性用于给logback上下文(Context)命名,它通常被用于在多个应用程序中分辨日志信息,-->
    <!--因为当不同应用程序使用同一个日志系统的时候,它们的日志信息可能会混淆。-->
    <!--应用程序可以为每个独立的实例设置一个不同的contextName属性值,以便于识别和区分来自不同应用程序的日志信息。-->
    <!--contextName属性值通常被用于日志输出等地方进行展示,它可以很方便地追踪应用程序的状态和运行情况。-->
    <!--举一个简单的例子,当一个应用程序分别运行在开发环境和生产环境中时,我们可以通过设置contextName属性为"dev"或"prod"来区分它们的输出日志信息。-->
    <!--当应用程序启动时,logback可以读取contextName属性,并进行相应的处理和配置。-->
    <!--属性-->
    <contextName>sleuth-server1</contextName>
    <!--属性-->
    <!--"logback-spring.xml"中的<property>元素用于定义属性和变量,并在配置文件中引用它们。<property>元素通常在配置文件中声明为根元素之前。在定义<property>元素后,可以使用 ${属性名} 或 ${变量名} 在配置文件中引用这些属性和变量。-->
    <!--以下是一个简单的示例,展示了如何在"logback-spring.xml"中使用<property>元素:-->
    <!--<configuration>-->
        <!--<property name="LOG_PATTERN" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/>-->
        <!--<appender name="FILE" class="ch.qos.logback.core.FileAppender">-->
            <!--<file>app.log</file>-->
            <!--<encoder>-->
                <!--<pattern>${LOG_PATTERN}</pattern>          &lt;!&ndash; 引用在<property>中定义的属性 &ndash;&gt;-->
            <!--</encoder>-->
        <!--</appender>-->
    <!--</configuration>-->
    <!--在上面的例子中,使用<property>元素在"logback-spring.xml"中定义一个名为"LOG_PATTERN"的属性,并设置了它的值。在<appender>元素中使用${LOG_PATTERN}引用了这个属性,从而实现了动态地设置输出日志的格式。通过使用<property>元素,我们可以在日志配置文件中定义和管理属性和变量,从而实现配置的灵活性和可读性。-->
    <!-- Example for logging into the build folder of your project -->
    <property name="LOG_FILE" value="${BUILD_FOLDER:-build}/${springAppName}"/>

    <!-- You can override this to have a custom pattern -->
    <!--这个日志格式定义了如下几个元素:-->
    <!--%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint}:输出当前时间,灰色显示,格式为yyyy-MM-dd HH:mm:ss.SSS。-->
    <!--%clr(${LOG_LEVEL_PATTERN:-%5p}):输出日志级别,不同级别使用不同颜色显示,级别名称不足5个字符右对齐。-->
    <!--%clr(${PID:- }){magenta}:输出进程 PID,麻雀粉色显示。-->
    <!--%clr(-&#45;&#45;){faint}:输出文本-&#45;&#45;,灰色显示。-->
    <!--%clr([%15.15t]){faint}:输出线程名缩写(最长15个字符),灰色显示。-->
    <!--%clr(%-40.40logger{39}){cyan}:输出logger名称,不超过40个字符,超出的进行裁剪,蓝绿色显示。-->
    <!--%clr(:){faint}:输出文本:,灰色显示。-->
    <!--%m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}:输出日志消息和换行符,如果有异常则输出异常堆栈信息。-->
    <!--例如,如果我们有下面的日志记录:-->
    <!--2019-02-01 15:23:03.235  INFO 54220 -&#45;&#45; [main] com.example.demo.DemoApplication  : Started DemoApplication in 3.298 seconds (JVM running for 3.737)-->
    <!--2019-02-01 15:23:03.235  INFO 54220 *** -&#45;&#45; [           main] c.e.d.DemoApplication                      : Started DemoApplication in 3.298 seconds (JVM running for 3.737)-->
    <property name="CONSOLE_LOG_PATTERN"
              value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>

    <!--节点-->
    <!-- Appender to log to console -->
    <!--"logback-spring.xml"中的<appender>元素用于指定输出日志的目的地,例如控制台、文件等。可以定义多个<appender>元素,并为每个元素指定一个名称,以便在<logger>或<root>元素中引用。-->
    <!--以下是一个简单的示例,展示了如何在"logback-spring.xml"中使用<appender>元素:-->
    <!--<configuration>-->
        <!--<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">-->
            <!--<encoder>-->
                <!--<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>-->
            <!--</encoder>-->
        <!--</appender>-->

        <!--<appender name="FILE" class="ch.qos.logback.core.FileAppender">-->
            <!--<file>app.log</file>-->
            <!--<encoder>-->
                <!--<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>-->
            <!--</encoder>-->
        <!--</appender>-->
        <!-- 其他配置 -->
        <!--<root level="INFO">-->
            <!--<appender-ref ref="CONSOLE"/>-->
            <!--<appender-ref ref="FILE"/>-->
        <!--</root>-->
    <!--</configuration>-->
    <!--在上面的例子中,定义了两个<appender>元素,分别为"CONSOLE"和"FILE",并分别为它们设置输出格式。在<root>元素中,分别使用<appender-ref>元素引用了这两个<appender>元素,作为输出日志的目的地。这样可以实现多重日志记录目的地,例如同时输出到控制台和日志文件中。通过使用<appender>元素,我们可以在日志配置文件中灵活地配置和管理输出日志的目的地并实现日志记录的高效性和低延迟性。-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <!--"logback-spring.xml"中的<filter>元素是应用于<appender>元素的一项特殊功能。它允许定义过滤器以决定哪些日志事件应该被发送到<appender>中,而哪些则应该被忽略。-->
    <!--一些常见的例子包括:-->
    <!--ThresholdFilter:只输出高于某个级别的日志(如INFO、WARN、ERROR等)。-->
    <!--DuplicateFilter:过滤重复的日志事件,可以在一定程度上减少日志事件的数量。-->
    <!--DynamicThresholdFilter:动态地更改过滤器的阈值,以更好地管理和控制日志。-->
    <!--下面是一个简单的示例,展示了如何在"logback-spring.xml"中使用<filter>元素:-->
    <!--<configuration>-->
        <!--<appender name="FILE" class="ch.qos.logback.core.FileAppender">-->
            <!--<file>app.log</file>-->
            <!--<filter class="ch.qos.logback.classic.filter.ThresholdFilter">-->
                <!--<level>WARN</level>                     &lt;!&ndash; 只输出高于WARN级别的日志 &ndash;&gt;-->
            <!--</filter>-->
            <!--<encoder>-->
                <!--<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>-->
            <!--</encoder>-->
        <!--</appender>-->
        <!-- 其他配置 -->
        <!--<root level="INFO">-->
            <!--<appender-ref ref="CONSOLE"/>-->
            <!--<appender-ref ref="FILE"/>-->
        <!--</root>-->
    <!--</configuration>-->
    <!--在上面的例子中,使用<filter>元素定义了一个名为"ThresholdFilter"的过滤器,并设置了过滤级别为WARN。这意味着只有高于WARN级别的日志事件,才会被输出到指定的<appender>中。通过使用<filter>元素,可以实现更加精细和高效的日志管理和记录。-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <!-- Minimum logging level to be presented in the console logs-->
            <level>DEBUG</level>
        </filter>
    <!--"logback-spring.xml"中的<encoder>元素用于指定输出日志的格式,它定义了一个或多个模板,并根据这些模板生成格式化的日志事件。-->
    <!--<encoder>元素内包含一个或多个<PatternLayout>元素,每个<PatternLayout>元素都为日志格式定义了一个模板。这些模板使用特殊字符,如%d(代表日期)、%p(代表日志级别)、%t(代表线程名称)、%m(代表日志信息)等,来生成格式化的日志事件。-->
    <!--以下是一个简单的示例,展示了如何在"logback-spring.xml"中使用<encoder>元素:-->
    <!--<configuration>-->
        <!--<appender name="FILE" class="ch.qos.logback.core.FileAppender">-->
            <!--<file>app.log</file>-->
            <!--<encoder>-->
                <!--<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>-->
            <!--</encoder>-->
        <!--</appender>-->
        <!-- 其他配置 -->
        <!--<root level="INFO">-->
            <!--<appender-ref ref="CONSOLE"/>-->
            <!--<appender-ref ref="FILE"/>-->
        <!--</root>-->
    <!--</configuration>-->
    <!--在上面的例子中,<encoder>元素定义了一个名为"FILE"的<appender>元素用于输出日志到文件中,并设置了输出日志的格式模板,包含了日期、线程名称、日志级别、类名、行数和日志信息等内容。-->
    <!--通过使用<encoder>元素,可以更加灵活地管理和配置输出日志的格式,并实现定制化、精细化的日志记录和管理。-->
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>

    <!-- Appender to log to file -->
    <!--"logback-spring.xml"中的<appender>元素可以指定不同的"class"属性值来实现不同的日志输出方式和技术。以下是几个常用的appender class属性值以及它们的意义:-->
    <!--ch.qos.logback.core.ConsoleAppender: 将日志输出到控制台(标准输出)。-->
    <!--ch.qos.logback.core.FileAppender: 将日志输出到文件,并可以设置输出文件的路径和格式。-->
    <!--ch.qos.logback.classic.net.SyslogAppender: 将日志输出到系统日志中(仅支持Unix系统)。-->
    <!--org.apache.log4j.net.SocketAppender: 将日志以TCP/UDP协议发送到远程服务器。-->
    <!--ch.qos.logback.classic.AsyncAppender: 提供异步日志输出功能,可加速日志记录操作。-->
    <!--除了这些常见的appender class属性值以外,Logback还提供了许多其他类型的appender,如JMS、SMTP、数据库、数据库等,可以根据具体应用场景的需要选择合适的appender class属性值来实现不同的日志输出方式和技术。-->
    <!--总之,通过为<appender>元素指定适当的class属性值,可以非常灵活地配置和管理日志输出,从而满足不同应用场景的需要。-->
    <appender name="flatfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>

    <!-- Appender to log to file in a JSON format -->
    <appender name="logstash" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE}.json</file>
        <!--在 logback-spring.xml 配置文件中,<rollingPolicy> 标签用于定义日志文件的滚动策略。class 属性用于指定滚动策略的具体实现类。以下是一些常用的滚动策略实现类及其含义:-->
        <!--1. ch.qos.logback.core.rolling.TimeBasedRollingPolicy:基于时间的滚动策略。根据指定的时间间隔(如每天、每小时等)滚动日志文件。通常与 %d 转换词一起使用,以在文件名中包含时间信息。-->
        <!--示例:-->
        <!--<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
            <!--<fileNamePattern>logs/app-%d{yyyy-MM-dd}.log</fileNamePattern>-->
        <!--</rollingPolicy>-->
        <!--2. ch.qos.logback.core.rolling.FixedWindowRollingPolicy:固定窗口滚动策略。根据指定的最大日志文件数量滚动日志文件。当达到最大文件数量时,最早的日志文件将被删除。-->
        <!--示例:-->
        <!--<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">-->
            <!--<fileNamePattern>logs/app-%i.log</fileNamePattern>-->
            <!--<minIndex>1</minIndex>-->
            <!--<maxIndex>10</maxIndex>-->
        <!--</rollingPolicy>-->
        <!--3. ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy:基于大小的滚动策略。当日志文件达到指定大小时,滚动日志文件。通常与 %i 转换词一起使用,以在文件名中包含索引信息。-->
        <!--示例:-->
        <!--<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">-->
            <!--<maxFileSize>10MB</maxFileSize>-->
        <!--</triggeringPolicy>-->
        <!--请注意,这些滚动策略可以单独使用,也可以组合使用,以满足不同的日志滚动需求。例如,您可以将基于时间的滚动策略与基于大小的触发策略组合使用,以在日志文件达到指定大小或时间间隔时滚动日志文件-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}.json.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <!--在 logback-spring.xml 配置文件中,<encoder> 标签用于定义日志消息的编码方式。class 属性用于指定编码器的具体实现类。以下是一些常用的编码器实现类及其含义:-->
        <!--1. ch.qos.logback.classic.encoder.PatternLayoutEncoder:模式布局编码器。它允许您自定义日志消息的格式,通过指定模式字符串来控制日志输出的内容和格式。这是 Logback 中最常用的编码器。-->
        <!--示例:-->
        <!--<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">-->
            <!--<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>-->
        <!--</encoder>-->
        <!--2. ch.qos.logback.core.encoder.LayoutWrappingEncoder:布局包装编码器。它允许您将自定义的 Layout 实现类应用于日志消息。这在需要更高级别的自定义时可能会用到。-->
        <!--示例:-->
        <!--<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
            <!--<layout class="com.example.CustomLayout" />-->
        <!--</encoder>-->
        <!--3. net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder:Logstash JSON 编码器。它将日志消息编码为 JSON 格式,以便与 Logstash 集成。这需要添加 Logstash Logback Encoder 依赖到您的项目中。-->
        <!--示例:-->
        <!--<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">-->
            <!--<providers>-->
                <!--<timestamp>-->
                    <!--<timeZone>UTC</timeZone>-->
                <!--</timestamp>-->
                <!--<pattern>-->
                    <!--<pattern>-->
                        <!--{-->
                        <!--"level": "%level",-->
                        <!--"logger": "%logger",-->
                        <!--"message": "%message"-->
                        <!--}-->
                    <!--</pattern>-->
                <!--</pattern>-->
            <!--</providers>-->
        <!--</encoder>-->
        <!--为了使用 Logstash JSON 编码器,您需要在项目的 pom.xml 文件中添加以下依赖:-->
        <!--<dependency>-->
            <!--<groupId>net.logstash.logback</groupId>-->
            <!--<artifactId>logstash-logback-encoder</artifactId>-->
            <!--<version>6.6</version>-->
        <!--</dependency>-->
        <!--请注意,您需要将 <version> 标签中的版本号替换为您想要使用的 Logstash Logback Encoder 的版本。您可以在 [Maven Repository](https://mvnrepository.com/artifact/net.logstash.logback/logstash-logback-encoder) 上找到最新版本。-->
        <!--这些编码器可以根据您的需求进行选择和配置。通常情况下,PatternLayoutEncoder 能满足大多数日志格式化需求。如果您需要更高级别的自定义或与其他系统集成,可以考虑使用其他编码器-->
        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp>
                    <timeZone>UTC</timeZone>
                </timestamp>
                <pattern>
                    <pattern>
                        {
                        "timestamp": "@timestamp",
                        "severity": "%level",
                        "service": "${springAppName:-}",
                        "trace": "%X{traceId:-}",
                        "span": "%X{spanId:-}",
                        "baggage": "%X{key:-}",
                        "pid": "${PID:-}",
                        "thread": "%thread",
                        "class": "%logger{40}",
                        "rest": "%message"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
    </appender>

    <!--在 logback-spring.xml 配置文件中,<springProfile> 标签用于根据 Spring Boot 的激活配置文件(Profile)来定义不同的日志配置。这使得您可以为不同的环境(如开发、测试、生产等)提供不同的日志配置。-->
    <!--<springProfile> 标签可以包含其他 Logback 配置元素,如 <appender>、<logger> 和 <root>。当 Spring Boot 激活的配置文件与 <springProfile> 标签的 name 属性匹配时,该标签内的日志配置将被应用。-->
    <!--以下是一个示例,展示了如何使用 <springProfile> 标签为不同的环境提供不同的日志级别:-->
    <!--<configuration>-->
        <!--<springProfile name="dev">-->
            <!--<logger name="com.example" level="DEBUG" />-->
        <!--</springProfile>-->

        <!--<springProfile name="prod">-->
            <!--<logger name="com.example" level="INFO" />-->
        <!--</springProfile>-->
    <!--</configuration>-->
    <!--在这个示例中,当 Spring Boot 激活的配置文件为 "dev" 时,com.example 包的日志级别将被设置为 DEBUG。当激活的配置文件为 "prod" 时,日志级别将被设置为 INFO。-->
    <!--要激活特定的配置文件,您可以在 application.properties 或 application.yml 文件中设置 spring.profiles.active 属性,或者在启动应用程序时通过命令行参数设置:-->
    <!--spring.profiles.active=dev-->
    <!--或者-->
    <!--spring:-->
        <!--profiles:-->
            <!--active: dev-->
    <!--命令行参数示例:-->
    <!--java -jar myapp.jar &#45;&#45;spring.profiles.active=dev-->
    <!--通过使用 <springProfile> 标签,您可以根据不同的环境和需求灵活地配置日志-->
    <!--环境配置-->
    <springProfile name="logzio">
        <!-- Use shutdownHook so that we can close gracefully and finish the log drain -->
        <!--<shutdownHook> 标签在 Logback 配置文件(如 logback.xml 或 logback-spring.xml)中的作用是在应用程序关闭时确保日志系统能够正常地完成日志记录。它通过注册一个 JVM 关闭钩子(Shutdown Hook)来实现这一功能。-->
        <!--当应用程序关闭时,JVM 关闭钩子会触发 Logback 的 LoggerContext 停止,从而确保所有的日志事件都被处理,缓冲区中的日志被刷新到磁盘,以及释放与日志记录相关的资源。-->
        <!--要在 Logback 配置文件中启用 <shutdownHook>,只需将以下代码添加到配置文件中:-->
        <!--这将注册一个 ch.qos.logback.core.hook.DelayingShutdownHook 类的实例作为 JVM 关闭钩子。DelayingShutdownHook 类是 Logback 提供的默认实现,它会在应用程序关闭时确保日志系统能够正常地完成日志记录。-->
        <!--请注意,如果您使用的是 Spring Boot,那么 <shutdownHook> 通常不需要显式添加,因为 Spring Boot 会自动注册一个关闭钩子来处理日志记录。但是,在某些情况下,您可能需要手动添加 <shutdownHook> 以确保日志记录在应用程序关闭时能够正常完成-->
        <shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
        <appender name="LogzioLogbackAppender" class="io.logz.logback.LogzioLogbackAppender">
            <!--在 logback-spring.xml 文件中,<token> 标签是 io.logz.logback.LogzioLogbackAppender 的一个配置元素,用于指定 Logz.io API 的访问令牌。Logz.io 是一个云日志管理平台,它提供了一种简单的方式来收集、分析和可视化您的应用程序日志。-->
            <!--${LOGZ_IO_API_TOKEN} 是一个占位符,它表示您需要在 logback-spring.xml 文件中提供一个具体的 Logz.io API 访问令牌。您可以在 Logz.io 网站上创建一个帐户,并生成一个 API 访问令牌,然后将其添加到 logback-spring.xml 文件中的 <token> 标签中。-->
            <!--例如,如果您的 Logz.io API 访问令牌是 1234567890abcdefg,则您的 logback-spring.xml 文件中的 <token> 标签应该如下所示:-->
            <!--<appender name="LogzioLogbackAppender" class="io.logz.logback.LogzioLogbackAppender">-->
                <!--<token>1234567890abcdefg</token>-->
                <!--<logzioUrl>https://listener.logz.io:8071</logzioUrl>-->
                <!--<filter class="ch.qos.logback.classic.filter.ThresholdFilter">-->
                    <!--<level>INFO</level>-->
                <!--</filter>-->
                <!--<debug>true</debug>-->
                <!--<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">-->
                    <!--<providers>-->
                        <!--<timestamp>-->
                            <!--<timeZone>UTC</timeZone>-->
                        <!--</timestamp>-->
                        <!--<pattern>-->
                            <!--<pattern>-->
                                <!--{-->
                                <!--"timestamp": "@timestamp",-->
                                <!--"severity": "%level",-->
                                <!--"service": "${springAppName:-}",-->
                                <!--"trace": "%X{traceId:-}",-->
                                <!--"span": "%X{spanId:-}",-->
                                <!--"baggage": "%X{key:-}",-->
                                <!--"pid": "${PID:-}",-->
                                <!--"thread": "%thread",-->
                                <!--"class": "%logger{40}",-->
                                <!--"rest": "%message"-->
                                <!--}-->
                            <!--</pattern>-->
                        <!--</pattern>-->
                    <!--</providers>-->
                <!--</encoder>-->
            <!--</appender>-->
            <!--请注意,您需要将 <token> 标签中的占位符 ${LOGZ_IO_API_TOKEN} 替换为您的实际 Logz.io API 访问令牌。这将确保 Logz.io Logback Appender 能够正确地将日志事件发送到您的 Logz.io 帐户-->
            <token>${LOGZ_IO_API_TOKEN}</token>
            <logzioUrl>https://listener.logz.io:8071</logzioUrl>
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>INFO</level>
            </filter>
            <debug>true</debug>
            <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                <providers>
                    <timestamp>
                        <timeZone>UTC</timeZone>
                    </timestamp>
                    <pattern>
                        <pattern>
                            {
                            "timestamp": "@timestamp",
                            "severity": "%level",
                            "service": "${springAppName:-}",
                            "trace": "%X{traceId:-}",
                            "span": "%X{spanId:-}",
                            "baggage": "%X{key:-}",
                            "pid": "${PID:-}",
                            "thread": "%thread",
                            "class": "%logger{40}",
                            "rest": "%message"
                            }
                        </pattern>
                    </pattern>
                </providers>
            </encoder>
        </appender>

        <!--节点-->
        <root level="info">
            <!-- IMPORTANT: make sure to include this line, otherwise the appender won't be used -->
            <appender-ref ref="LogzioLogbackAppender"/>
        </root>
    </springProfile>
    <!--在logback.xml或logback-spring.xml中,<logger>元素用于为指定的包名或类名设置日志级别或引用附加器等。它可以在<root>元素之前或之后被定义,可以类比为<root>元素的子级。-->
    <!--<logger>元素有下列属性:-->
    <!--name:指定要设置的包名或类名,为空时表示所有 logger 都应该应用该配置,与<root>相同。-->
    <!--level:指定日志输出级别,可选值有:TRACE、DEBUG、INFO、WARN、ERROR、OFF,级别依次递增,NOT_SET其实是从来没有设置过级别,或是在XML文件中没有显式地指定过级别。-->
    <!--additivity:指定当前logger是否继承父logger的appender,取值为true或false,默认为true。-->
    <!--与<root>的区别是,<root>设置的日志输出级别是最顶层的,而<logger>则基于包名或类名来定义不同级别的日志输出策略,因此<logger>可以针对不同类或不同包的日志输出进行定制,而<root>则是全局设置。<logger>元素的输出优先级高于<root>元素。-->
    <!--可以通过下面的例子理解<root>与<logger>的关系:-->
    <!--<root level="INFO">-->
        <!--<appender-ref ref="STDOUT" />-->
    <!--</root>-->
    <!--<logger name="com.foo.Bar" level="DEBUG" additivity="false">-->
        <!--<appender-ref ref="BAR-STDOUT" />-->
    <!--</logger>-->
    <!--该配置表示根级别的日志输出级别为INFO,同时关联了STDOUT附加器;针对com.foo.Bar包下的日志使用DEBUG级别输出,并关联了BAR-STDOUT附加器。其中,<logger>的additivity属性设置为false,表示当前logger不继承父logger的appender,防止父logger中可能的重复输出。-->
    <logger name="com.example.springcloudsleuthdemo.controller.SleuthController" level="DEBUG" additivity="false">
        <appender-ref ref="console"/>
    </logger>

    <!--节点-->
    <!--在 logback-spring.xml 配置文件中,<root> 标签用于定义根日志记录器。根日志记录器是 Logback 中最基本的日志记录器,它会接收所有未被其他日志记录器处理的日志事件。您可以使用 <level> 标签来指定根日志记录器的日志级别,以控制哪些日志事件将被记录。-->
    <!--<appender-ref> 标签用于将日志事件发送到一个或多个附加器(Appender)。附加器是 Logback 中用于将日志事件输出到不同目的地的组件,例如控制台、文件、数据库等。通过使用 <appender-ref> 标签,您可以将根日志记录器的日志事件发送到一个或多个附加器,以便将日志记录到多个目的地。-->
    <!--以下是一个示例,展示了如何在 logback-spring.xml 文件中定义根日志记录器和附加器:-->
    <!--<configuration>-->
        <!--<appender name="ConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">-->
            <!--<encoder>-->
                <!--<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>-->
            <!--</encoder>-->
        <!--</appender>-->

        <!--<appender name="FileAppender" class="ch.qos.logback.core.FileAppender">-->
            <!--<file>logs/myapp.log</file>-->
            <!--<encoder>-->
                <!--<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>-->
            <!--</encoder>-->
        <!--</appender>-->

        <!--<root level="INFO">-->
            <!--<appender-ref ref="ConsoleAppender" />-->
            <!--<appender-ref ref="FileAppender" />-->
        <!--</root>-->
    <!--</configuration>-->
    <!--在这个示例中,我们定义了两个附加器:ConsoleAppender 和 FileAppender。ConsoleAppender 用于将日志事件输出到控制台,FileAppender 用于将日志事件输出到文件。然后,我们定义了根日志记录器,并将其日志级别设置为 INFO。最后,我们使用 <appender-ref> 标签将根日志记录器的日志事件发送到 ConsoleAppender 和 FileAppender 附加器。-->
    <!--通过使用 <root> 和 <appender-ref> 标签,您可以在 logback-spring.xml 文件中定义根日志记录器和附加器,并将日志事件记录到多个目的地。这使得您可以更好地控制日志记录,并将日志记录到适当的位置,以便进行故障排除和分析。-->
    <root level="INFO">
        <appender-ref ref="console"/>
        <!-- uncomment this to have also JSON logs -->
        <appender-ref ref="logstash"/>
        <appender-ref ref="flatfile"/>
    </root>
</configuration>

4、自定义MDC

示例:

2023-06-07 10:21:02.971 INFO [,,,] 14676 --- [ main] c.e.s.SpringCloudSleuthDemoApplication : Started SpringCloudSleuthDemoApplication in 4.397 seconds (JVM running for 5.68)

这个日志格式中,[,,,]这一部分表示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.put("requestId", "123456");
logger.info("This is a test log message with requestId={}", MDC.get("requestId"));

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

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

<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
  <encoder>
    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - [%X{requestId}] %msg%n</pattern>
  </encoder>
</appender>

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

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

在Spring Cloud Sleuth中,MDC默认记录[appname,traceId,spanId,exportable]:

  • appname:记录跨度的应用程序的名称。

  • spanId:发生的特定操作的ID。

  • traceId:包含span的延迟图的ID。

  • exportable:是否将日志导出到Zipkin。

2016-02-02 15:31:01.936  INFO [bar,46ab0d418373cbc9,46ab0d418373cbc9,false] 23030 --- [nio-8081-exec-4] ...

猜你喜欢

转载自blog.csdn.net/qq_27890899/article/details/131083155