链路追踪

Spring Boot Actuator 提供了对 Micrometer Tracing 的依赖管理和自动配置,Micrometer Tracing 是一个流行追踪器库的门面。

要了解 Micrometer Tracing 的更多功能,请参阅其 参考文档

支持的追踪器

Spring Boot 提供以下追踪器的自动配置:

入门

我们需要一个示例应用来演示如何开始链路追踪。 这里我们使用 开发您的第一个 Spring Boot 应用程序 部分介绍的简单“Hello World!”Web 应用。 我们将使用 OpenTelemetry 追踪器,并以 Zipkin 作为追踪后端。

回顾一下,主应用代码如下:

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);
	}

}
home() 方法中增加了 logger 语句,这一点后续会用到。

现在需要添加以下依赖:

  • org.springframework.boot:spring-boot-starter-actuator

  • io.micrometer:micrometer-tracing-bridge-otel - 将 Micrometer Observation API 桥接到 OpenTelemetry。

  • io.opentelemetry:opentelemetry-exporter-zipkin - 将 traces 上报到 Zipkin。

添加如下应用配置:

  • Properties

  • YAML

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

默认情况下,Spring Boot 只采样 10% 的请求以避免追踪后端压力过大。 此配置将采样率调整为 100%,即每个请求都会发送到追踪后端。

为了收集和可视化追踪数据,我们需要一个正在运行的追踪后端。 这里我们使用 Zipkin 作为追踪后端。 Zipkin 快速入门指南 提供了本地启动 Zipkin 的说明。

Zipkin 启动后,可以启动你的应用。

在浏览器访问 localhost:8080,你应该会看到如下输出:

Hello World!

在幕后,HTTP 请求会创建一个 observation,该 observation 会桥接到 OpenTelemetry,并最终上报新的 trace 到 Zipkin。

现在打开 Zipkin UI(localhost:9411),点击“Run Query”按钮即可列出所有已收集的追踪。 你应该能看到一个 trace。 点击“Show”按钮可查看该 trace 的详细信息。

日志关联 ID(Correlation IDs)

关联 ID 可帮助你将日志文件中的行与 span/trace 关联起来。 如果你使用 Micrometer Tracing,Spring Boot 默认会在日志中包含关联 ID。

默认的关联 ID 由 traceIdspanId MDC 值组成。 例如,Micrometer Tracing 添加了 MDC traceId803B448A0489F84084905D3093480352 和 MDC spanId3425F23BB2432450,日志输出将包含关联 ID [803B448A0489F84084905D3093480352-3425F23BB2432450]

如果你希望使用不同格式的关联 ID,可以通过 logging.pattern.correlation 属性自定义。 例如,下面的配置将为 Logback 提供与 Spring Cloud Sleuth 之前格式一致的关联 ID:

  • Properties

  • YAML

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 末尾包含一个空格,以便与后续 logger 名称默认分隔。
关联 ID 依赖上下文传播。 详细说明请参阅 此文档

Trace 传播

要自动在网络上传播 trace,请使用自动配置的 RestTemplateBuilderRestClient.BuilderWebClient.Builder 构建客户端。

如果你直接创建 RestTemplateRestClientWebClient,而未使用自动配置的 builder,则无法实现 trace 自动传播!

追踪器实现

Micrometer Tracer 支持多种追踪器实现,因此在 Spring Boot 中可组合多种依赖。

所有追踪器实现都需要 org.springframework.boot:spring-boot-starter-actuator 依赖。

OpenTelemetry 配合 Zipkin

使用 OpenTelemetry 并上报到 Zipkin 需要以下依赖:

  • io.micrometer:micrometer-tracing-bridge-otel - 将 Micrometer Observation API 桥接到 OpenTelemetry。

  • io.opentelemetry:opentelemetry-exporter-zipkin - 将 trace 上报到 Zipkin。

通过 management.zipkin.tracing.* 配置属性可设置上报到 Zipkin 的相关参数。

OpenTelemetry 配合 Wavefront

使用 OpenTelemetry 并上报到 Wavefront 需要以下依赖:

  • io.micrometer:micrometer-tracing-bridge-otel - 将 Micrometer Observation API 桥接到 OpenTelemetry。

  • io.micrometer:micrometer-tracing-reporter-wavefront - 将 trace 上报到 Wavefront。

通过 management.wavefront.* 配置属性可设置上报到 Wavefront 的相关参数。

OpenTelemetry 配合 OTLP

使用 OpenTelemetry 并通过 OTLP 上报需要以下依赖:

  • io.micrometer:micrometer-tracing-bridge-otel - 将 Micrometer Observation API 桥接到 OpenTelemetry。

  • io.opentelemetry:opentelemetry-exporter-otlp - 将 trace 上报到可接收 OTLP 的采集器。

通过 management.otlp.tracing.* 配置属性可设置 OTLP 上报参数。

如果需要对 OTLP span exporter 进行高级自定义,可注册 OtlpHttpSpanExporterBuilderCustomizerOtlpGrpcSpanExporterBuilderCustomizer bean。 这些自定义器会在 OtlpHttpSpanExporterOtlpGrpcSpanExporter 创建前被调用,并优先于自动配置应用的设置。

OpenZipkin Brave 配合 Zipkin

使用 OpenZipkin Brave 并上报到 Zipkin 需要以下依赖:

  • io.micrometer:micrometer-tracing-bridge-brave - 将 Micrometer Observation API 桥接到 Brave。

  • io.zipkin.reporter2:zipkin-reporter-brave - 将 trace 上报到 Zipkin。

通过 management.zipkin.tracing.* 配置属性可设置上报到 Zipkin 的相关参数。

OpenZipkin Brave 配合 Wavefront

使用 OpenZipkin Brave 并上报到 Wavefront 需要以下依赖:

  • io.micrometer:micrometer-tracing-bridge-brave - 将 Micrometer Observation API 桥接到 Brave。

  • io.micrometer:micrometer-tracing-reporter-wavefront - 将 trace 上报到 Wavefront。

通过 management.wavefront.* 配置属性可设置上报到 Wavefront 的相关参数。

与 Micrometer Observation 集成

TracingAwareMeterObservationHandler 会自动注册到 ObservationRegistry 上,每个已完成的 observation 都会创建 span。

创建自定义 Span

你可以通过启动 observation 创建自定义 span。 为此,将 ObservationRegistry 注入你的组件:

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 ...
		});
	}

}

这会创建一个名为“some-operation”,带有标签“some-tag=some-value”的 observation。

如果你只想创建 span 而不创建 metric,可使用 Micrometer 的 底层 Tracer API

Baggage(携带数据)

你可以通过 Tracer API 创建 baggage:

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
		}
	}

}

此示例创建名为 baggage1、值为 value1 的 baggage。 如果你使用 W3C 传播方式,baggage 会自动在网络上传播。 如果使用 B3 传播,baggage 不会自动传播。 如需手动传播 baggage,可使用 management.tracing.baggage.remote-fields 配置属性(W3C 方式同样适用)。 如上述示例,将该属性设置为 baggage1,则会产生 HTTP 头 baggage1: value1

如需将 baggage 传播到 MDC,可使用 management.tracing.baggage.correlation.fields 配置属性。 如上述示例,将该属性设置为 baggage1,则会在 MDC 中生成名为 baggage1 的条目。

测试

在使用 @SpringBootTest 时,负责上报数据的追踪组件不会被自动配置。 更多细节请参阅 使用追踪