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