GuanceCloud / dd-trace-java

Datadog APM client for Java
https://docs.datadoghq.com/tracing/languages/java
Apache License 2.0
9 stars 3 forks source link

在多传播协议下,traceid 出现转换异常 #82

Open lrwh opened 4 months ago

lrwh commented 4 months ago

DDTrace 默认开启两种传播协议:datadogtraceparent(W3C协议)

在高并发情况下,不同的请求方对 traceId 生成存在“干涉”行为。导致以下请求头,生成的span traceId 不是原来的值

Header

x-datadog-parent-id: 104339551990828450
x-datadog-trace-id: 1635233488710803284
x-datadog-origin: rum

而导致这一问题是因为 DatadogHttpCodec 解码器调用了restore128bTraceId(),致使 traceId 发生了变化。

    protected TagContext build() {
      restore128bTraceId();
      return super.build();
    }

    private void restore128bTraceId() {
      long highOrderBits;
      // Check if the low-order 64 bits of the TraceId, and propagation tags were parsed
      if (traceId != DDTraceId.ZERO
          && propagationTags != null
          && (highOrderBits = propagationTags.getTraceIdHighOrderBits()) != 0) {
        // Restore the 128-bit TraceId
        traceId = DD128bTraceId.from(highOrderBits, traceId.toLong());
      }
    }

而导致方法restore128bTraceId()改写 traceId的主要原因是 propagationTags.getTraceIdHighOrderBits()getTraceIdHighOrderBits()是用于获取 traceId 的高位码。

由于 datadog 协议默认 traceId 是 64 位,而 W3C 协议 traceId 是 128 位的,为了做兼容处理,所以需要补码处理。补码也是依据请求头x-datadog-tags来进行补码的。

从最上面的 Header 来看,并没有x-datadog-tags,也就说改变这一行为是由于其他链路的请求头导致的,propagationTags 参数值受到了影响,由于这个变量没有”及时的恢复或者清空“,导致了这一结果发生。

lrwh commented 4 months ago

目前采用临时方案解决:rum端调整为 w3c 协议。