此版本仍在开发中,尚未被视为稳定版本。如需最新稳定版本,请使用 Spring Boot 4.0.4!spring-doc.cadn.net.cn

链路追踪

Spring Boot Actuator 为 Micrometer Tracing 提供依赖管理和自动配置,Micrometer Tracing 是流行追踪器库的外观层。spring-doc.cadn.net.cn

了解有关 Micrometer Tracing 功能的更多信息,请参阅其 参考文档

支持的追踪器

Spring Boot 为以下追踪器提供了自动配置:spring-doc.cadn.net.cn

入门指南

我们需要一个示例应用程序,以便开始进行跟踪。 对于我们的目的,开发您的第一个 Spring Boot 应用程序 部分中介绍的简单“Hello World!”网络应用程序就足够了。 我们将使用 Brave 跟踪器和 Zipkin 作为跟踪后端。spring-doc.cadn.net.cn

回顾一下,我们的主要应用程序代码如下所示:spring-doc.cadn.net.cn

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class MyApplication {

	private static final Log logger = LogFactory.getLog(MyApplication.class);

	@RequestMapping("/")
	String home() {
		logger.info("home() has been called");
		return "Hello World!";
	}

	public static void main(String[] args) {
		SpringApplication.run(MyApplication.class, args);
	}

}
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@SpringBootApplication
class MyApplication {

	private val logger: Log = LogFactory.getLog(MyApplication::class.java)

	@RequestMapping("/")
	fun home(): String {
		logger.info("home() has been called")
		return "Hello, World!"
	}

}

fun main(args: Array<String>) {
	runApplication<MyApplication>(*args)
}
home() 方法中添加了一条 logger 语句,这将在后面变得重要。

现在我们必须添加 org.springframework.boot:spring-boot-starter-zipkin 依赖项。spring-doc.cadn.net.cn

然后添加以下应用程序属性:spring-doc.cadn.net.cn

management.tracing.sampling.probability=1
management:
  tracing:
    sampling:
      probability: 1.0

默认情况下,Spring Boot 仅对 10% 的请求进行采样,以防止过多地压垮跟踪后端。 此属性将其切换为 100%,以便每个请求都会发送到跟踪后端。spring-doc.cadn.net.cn

为了收集和可视化跟踪信息,我们需要一个运行中的跟踪后端。 我们在这里使用 Zipkin 作为我们的跟踪后端。 Zipkin 快速入门指南 提供了如何在本地启动 Zipkin 的说明。spring-doc.cadn.net.cn

Zipkin 运行后,您可以启动您的应用程序。spring-doc.cadn.net.cn

如果您在 Web 浏览器中打开 localhost:8080,应该会看到以下输出:spring-doc.cadn.net.cn

Hello World!

在幕后,已为HTTP请求创建了一个观察,该观察又会传递给Brave,Brave会向Zipkin报告一个新的跟踪信息。spring-doc.cadn.net.cn

现在在 localhost:9411 处打开 Zipkin UI,然后点击“Run Query”按钮以列出所有收集的追踪信息。 你应该会看到一条追踪记录。 点击“Show”按钮以查看该追踪记录的详细信息。spring-doc.cadn.net.cn

记录关联 ID

Correlation IDs 提供了一种有用的方法,将日志文件中的行与跨度/跟踪相关联。 如果您使用 Micrometer Tracing,Spring Boot 默认会在您的日志中包含 correlation IDs。spring-doc.cadn.net.cn

默认的相关性 ID 由 traceIdspanId MDC 值构建而成。 例如,如果 Micrometer Tracing 添加了一个值为 803B448A0489F84084905D3093480352 的 MDC traceId 和一个值为 3425F23BB2432450 的 MDC spanId,则日志输出将包含相关性 ID [803B448A0489F84084905D3093480352-3425F23BB2432450]spring-doc.cadn.net.cn

如果您希望使用不同的关联 ID 格式,可以使用 logging.pattern.correlation 属性来定义。 例如,以下配置将为 Logback 提供以前由 Spring Cloud Sleuth 使用的格式的关联 ID:spring-doc.cadn.net.cn

logging.pattern.correlation=[${spring.application.name:},%X{traceId:-},%X{spanId:-}] 
logging.include-application-name=false
logging:
  pattern:
    correlation: "[${spring.application.name:},%X{traceId:-},%X{spanId:-}] "
  include-application-name: false
在上面的示例中,logging.include-application-name 被设置为 false,以避免应用程序名称在日志消息中重复(logging.pattern.correlation 已包含它)。 还值得一提的是,logging.pattern.correlation 包含一个尾随空格,以便默认情况下与紧随其后的记录器名称分隔开。
关联 ID 依赖于上下文传播。 请阅读 此文档以获取更多详细信息

传播追踪信息

要通过网络自动传播跟踪信息,请使用自动配置的 RestTemplateBuilderRestClient.BuilderWebClient.Builder 来构建客户端。spring-doc.cadn.net.cn

如果您在不使用自动配置的构建器的情况下创建 RestTemplateRestClientWebClient,则自动跟踪传播将不起作用!

Tracer 实现

由于 Micrometer Tracer 支持多种追踪器实现,因此与 Spring Boot 的依赖组合可能有多种。 OpenTelemetry 与 OTLP 的组合以及 Brave 与 Zipkin 的组合较为常见,并且有专门的Starters。spring-doc.cadn.net.cn

使用 OTLP 的 OpenTelemetry

使用 OpenTelemetry 进行追踪并通过 OTLP 报告需要以下依赖项:spring-doc.cadn.net.cn

使用 management.opentelemetry.tracing.export.otlp.* 配置属性来配置基于 OTLP 的报告。spring-doc.cadn.net.cn

如果您需要对 OTLP 跨度导出器应用高级自定义,请考虑注册 OtlpHttpSpanExporterBuilderCustomizerOtlpGrpcSpanExporterBuilderCustomizer Bean。 这些将在创建 OtlpHttpSpanExporterOtlpGrpcSpanExporter 之前被调用。 自定义器的优先级高于自动配置应用的任何设置。

使用 Zipkin 的 OpenTelemetry

OpenTelemetry 已< a t="C0">弃用其 Zipkin 支持。 其自动配置将在 Spring Boot 4.2 中被移除。 请改用 Brave 或考虑使用< a t="C1">Zipkin OTel 模块来直接接收 OTLP。

使用 OpenTelemetry 进行追踪并报告到 Zipkin 需要以下依赖项:spring-doc.cadn.net.cn

  • org.springframework.boot:spring-boot-micrometer-tracing-opentelemetry - Spring Boot 对 OpenTelemetry 上 Micrometer Tracing 的支持。spring-doc.cadn.net.cn

  • io.micrometer:micrometer-tracing-bridge-otel - 将 Micrometer Observation API 桥接到 OpenTelemetry。spring-doc.cadn.net.cn

  • org.springframework.boot:spring-boot-zipkin - Spring Boot 对 Zipkin 的支持。spring-doc.cadn.net.cn

  • io.opentelemetry:opentelemetry-exporter-zipkin - 用于将跟踪报告到Zipkin的OpenTelemetry导出器。spring-doc.cadn.net.cn

使用 management.tracing.export.zipkin.* 配置属性来配置向 Zipkin 的报告。spring-doc.cadn.net.cn

使用 Zipkin 的 OpenZipkin Brave

使用 OpenZipkin Brave 进行链路追踪并上报到 Zipkin 需要以下依赖项:spring-doc.cadn.net.cn

使用 management.tracing.export.zipkin.* 配置属性来配置向 Zipkin 的报告。spring-doc.cadn.net.cn

采样

默认情况下,Spring Boot 仅对 10% 的请求进行采样,以防止过度负载追踪后端。 management.tracing.sampling.probability 属性可用于进行此配置。spring-doc.cadn.net.cn

在使用 OpenTelemetry 时,您还可以通过 management.opentelemetry.tracing.sampler 属性配置使用的采样器。 支持的采样器如下:spring-doc.cadn.net.cn

采样器 描述

always-onspring-doc.cadn.net.cn

每秒采样一次跟踪。spring-doc.cadn.net.cn

always-offspring-doc.cadn.net.cn

丢弃所有痕迹。spring-doc.cadn.net.cn

trace-id-ratiospring-doc.cadn.net.cn

根据 management.tracing.sampling.probability 对跟踪进行采样。spring-doc.cadn.net.cn

parent-based-always-onspring-doc.cadn.net.cn

如果父跨度被采样,则对子跨度进行采样。如果没有父级,则对每个跟踪进行采样。spring-doc.cadn.net.cn

parent-based-always-offspring-doc.cadn.net.cn

如果父跨度被采样,则对子跨度进行采样。如果没有父级,则丢弃所有跟踪。spring-doc.cadn.net.cn

parent-based-trace-id-ratio (默认)spring-doc.cadn.net.cn

如果父级span被采样,则对子span进行采样。如果没有父级,则根据management.tracing.sampling.probability对部分跟踪进行采样。spring-doc.cadn.net.cn

跨度限制

使用 OpenTelemetry 时,可以通过 management.opentelemetry.tracing.limits.* 配置属性配置跨度限制。 这些属性允许您控制每个跨度的最大属性数、事件和链接数,以及字符串属性值的最大长度。spring-doc.cadn.net.cn

例如,将每个跨度的属性数量限制为 64 个,最大属性值长度限制为 256 个字符:spring-doc.cadn.net.cn

management.opentelemetry.tracing.limits.max-attributes=64
management.opentelemetry.tracing.limits.max-attribute-value-length=256
management:
  opentelemetry:
    tracing:
      limits:
        max-attributes: 64
        max-attribute-value-length: 256

如果您需要完全控制,可以注册一个自定义的 SpanLimits bean。spring-doc.cadn.net.cn

与 Micrometer Observation 集成

TracingAwareMeterObservationHandler 会自动注册到 ObservationRegistry 上,后者会为每个已完成的观测创建跨度。spring-doc.cadn.net.cn

创建自定义 Span

您可以通过启动一个观测来创建自己的跨度。 为此,请将 ObservationRegistry 注入到您的组件中:spring-doc.cadn.net.cn

import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationRegistry;

import org.springframework.stereotype.Component;

@Component
class CustomObservation {

	private final ObservationRegistry observationRegistry;

	CustomObservation(ObservationRegistry observationRegistry) {
		this.observationRegistry = observationRegistry;
	}

	void someOperation() {
		Observation observation = Observation.createNotStarted("some-operation", this.observationRegistry);
		observation.lowCardinalityKeyValue("some-tag", "some-value");
		observation.observe(() -> {
			// Business logic ...
		});
	}

}
import io.micrometer.observation.Observation
import io.micrometer.observation.ObservationRegistry
import org.springframework.stereotype.Component

@Component
class CustomObservation(private val observationRegistry: ObservationRegistry) {

	fun someOperation() {
		Observation.createNotStarted("some-operation", observationRegistry)
			.lowCardinalityKeyValue("some-tag", "some-value")
			.observe {
				// Business logic ...
			}
	}

}

这将创建一个名为“some-operation”的观测,并带有标签“some-tag=some-value”。spring-doc.cadn.net.cn

如果你想要创建一个不创建指标的span,你需要使用Micrometer中的低级Tracer API

行李上下文

您可以使用 Tracer API 创建行李:spring-doc.cadn.net.cn

import io.micrometer.tracing.BaggageInScope;
import io.micrometer.tracing.Tracer;

import org.springframework.stereotype.Component;

@Component
class CreatingBaggage {

	private final Tracer tracer;

	CreatingBaggage(Tracer tracer) {
		this.tracer = tracer;
	}

	void doSomething() {
		try (BaggageInScope scope = this.tracer.createBaggageInScope("baggage1", "value1")) {
			// Business logic
		}
	}

}
import io.micrometer.tracing.Tracer
import org.springframework.stereotype.Component

@Component
class CreatingBaggage(private val tracer: Tracer) {

	fun doSomething() {
		tracer.createBaggageInScope("baggage1", "value1").use {
			// Business logic
		}
	}

}

此示例创建名为 baggage1 且值为 value1 的 baggage。 如果您使用的是 W3C 传播,baggage 会自动通过网络传播。 如果您使用的是 B3 传播,baggage 不会自动传播。 要手动通过网络传播 baggage,请使用 management.tracing.baggage.remote-fields 配置属性(这也适用于 W3C)。 对于上述示例,将此属性设置为 baggage1 将生成 HTTP 标头 baggage1: value1spring-doc.cadn.net.cn

如果要将 baggage 传播到 MDC,请使用 management.tracing.baggage.correlation.fields 配置属性。 对于上面的示例,将此属性设置为 baggage1 将生成一个名为 baggage1 的 MDC 条目。spring-doc.cadn.net.cn

测试

使用 @SpringBootTest 时,报告数据的追踪组件不会自动配置。 请参阅 使用追踪 以获取更多详细信息。spring-doc.cadn.net.cn