bigywater.tech
Spring · 129

Micrometer Tracing:链路 ID 进日志与跨服务传播

日志里的 traceId 是怎么来的?为什么我加了 micrometer-tracing 依赖什么都没有?默认采样多少?为什么下游收不到 traceparent?异步线程里的日志为什么没有 traceId?这篇用两个互相调用的服务在 Spring Boot 4.0.8 上逐项验证。

0 个
只加 micrometer-tracing-bridge-otel 依赖时,日志里的 traceId 个数,Boot 4 还需要 starter 里的自动配置
88 / 12
默认采样概率下,100 个请求里不采样与采样的个数
断开
RestClient.create() 和 new RestTemplate() 发出的请求下游收不到 traceparent

依赖

实测 · 本机执行输出
  [完全没有 tracing 依赖] A 的日志 traceId = 空;B 的日志 traceId = 空;B 收到的 traceparent = null
  [只加了 io.micrometer:micrometer-tracing-bridge-otel(没有 Spring Boot 的 tracing 自动配置)] A 的日志 traceId = 空;B 的日志 traceId = 空;B 收到的 traceparent = null

只加 bridge 无效;spring-boot-starter-opentelemetry 才有自动配置。

日志与传播

实测 · 本机执行输出
  A 的日志:A 收到请求 how=builder ← [svc-a] traceId 299c4a2f…(长 32),spanId 669344…(长 16)
  B 的日志:B 收到请求 ← [svc-b] traceId 299c4a2f…,spanId eb12d7…;traceId 与 A 相同,spanId 不同
  B 收到的 traceparent 头 = 00-…-00(格式 版本-32位traceId-16位spanId-标志位);标志位 = 00
  再发 100 个请求,B 收到的 traceparent 标志位统计:{'00': 88, '01': 12}(01 = 采样,00 = 不采样)

日志有 traceId-spanId;下游 traceId 相同、spanId 不同;W3C traceparent;默认采样 10%。

全量采样

实测 · 本机执行输出
  100 个请求的标志位统计:{'01': 100}

sampling.probability=1.0。

客户端创建方式

实测 · 本机执行输出
  注入的 RestClient.Builder:B 收到的 traceparent = 00-…-01;A 与 B 的 traceId 相同
  RestClient.create():B 收到的 traceparent = null(没有这个头);A 与 B 的 traceId 不同
  new RestTemplate():B 收到的 traceparent = null(没有这个头);A 与 B 的 traceId 不同

注入的 Builder 才传播。

线程

实测 · 本机执行输出
  自己 new 的 Executors 线程池:请求线程的日志 traceId=d23ced82…;线程池里的日志 traceId=空(没有 traceId),与请求线程不同
  Spring 的 applicationTaskExecutor:请求线程的日志 traceId=3beab57a…;线程池里的日志 traceId=空(没有 traceId),与请求线程不同
  Spring 的 applicationTaskExecutor,加了 ContextPropagatingTaskDecorator bean:请求线程的日志 traceId=b3229b9c…;线程池里的日志 traceId=b3229b9c…,与请求线程相同

新线程默认丢 traceId,ContextPropagatingTaskDecorator 可传播。

分步演示

链路追踪
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动。两个服务是同一个 jar 以不同端口启动(svc-a 调 svc-b);没有导出到 Zipkin / OTLP 后端,只看日志与请求头;spring-boot-starter-opentelemetry 默认带 OTLP 导出器,本机没有接收端
    • 没有验证:Brave 桥接(micrometer-tracing-bridge-brave)的行为与 B3 传播;spring-boot-starter-opentelemetry 到底引入了哪些自动配置模块(只确认缺它则无效);Feign / WebClient / Gateway 的传播;消息队列(Kafka / RabbitMQ)的传播;导出到 Zipkin / Tempo;@Async、@Scheduled 的上下文传播;baggage;采样器的其他配置(ParentBased 等)
    京ICP备2026067502号-1京公网安备11010502063487号