You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用远程上下文TraceId和SpanID仍生成新Trace与Span问题排查

问题:OpenTelemetry自定义Span无法关联Cloud Run父Trace

通过HTTP请求头传递的traceId和spanId构建远程上下文并创建新Span时,新Span未关联到预期的父Span,反而生成独立的TraceId。在Trace Explorer中可见,Cloud Run端点调用的默认Trace与Java代码生成的自定义Trace是两个独立Trace,而非同一Trace的层级结构。

问题代码

OpenTelemetry openTelemetry = AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk();

Tracer tracer = openTelemetry.getTracer(INSTRUMENTATION_NAME);

String[] ids = (headers.get("x-cloud-trace-context").split(";"))[0].split("/");

SpanContext remoteContext = SpanContext.createFromRemoteParent(
                    ids[0],
                    ids[1],
                    TraceFlags.getSampled(),
                    TraceState.getDefault());

Span span = tracer
            .spanBuilder("Make Call Out")
            .setParent(Context.current().with(Span.wrap(remoteContext)))
            .startSpan();

Span childSpan = tracer.spanBuilder("HTTP Request")
            .setParent(Context.current().with(span))
            .startSpan();
//Some Work
childSpan.end();
span.end();
问题排查与修复

核心问题点

  • 未绑定远程上下文到当前线程:代码仅在setParent时临时创建包含远程Span的Context,但未将其设置为当前线程的活跃Context,导致后续Span无法继承父Trace信息。
  • Cloud Run Trace ID格式不兼容:Cloud Run的x-cloud-trace-context中Trace ID为24位十六进制字符串,而OpenTelemetry要求Trace ID为32位(16字节),长度不匹配会被判定为无效ID,进而生成新Trace。

修复步骤

  1. 绑定远程上下文到当前线程
    使用Scope将远程上下文绑定到当前线程,确保后续创建的Span自动继承父Trace信息:

    // 解析请求头中的Trace信息
    String[] ids = (headers.get("x-cloud-trace-context").split(";"))[0].split("/");
    String cloudTraceId = ids[0];
    String cloudSpanId = ids[1];
    
    // 补全Cloud Run Trace ID到32位(OpenTelemetry要求的长度)
    String otelTraceId = String.format("%032x", new BigInteger(cloudTraceId, 16));
    
    // 构建远程Span上下文
    SpanContext remoteContext = SpanContext.createFromRemoteParent(
        otelTraceId,
        cloudSpanId,
        TraceFlags.getSampled(),
        TraceState.getDefault());
    
    // 将远程上下文设置为当前线程活跃上下文
    try (Scope remoteScope = Context.current().with(Span.wrap(remoteContext)).makeCurrent()) {
        // 创建子Span,自动继承父上下文
        Span span = tracer.spanBuilder("Make Call Out").startSpan();
        try (Scope spanScope = span.makeCurrent()) {
            Span childSpan = tracer.spanBuilder("HTTP Request").startSpan();
            // 执行业务逻辑
            childSpan.end();
        } finally {
            span.end();
        }
    }
    
  2. 确保SDK配置正确
    确认依赖中包含Cloud Trace相关的Exporter,保证Span能正确上报并关联:

    <dependency>
        <groupId>io.opentelemetry</groupId>
        <artifactId>opentelemetry-exporter-otlp</artifactId>
    </dependency>
    <dependency>
        <groupId>io.opentelemetry</groupId>
        <artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
    </dependency>
    

验证

修复后,在Trace Explorer中可看到Make Call Out和HTTP Request Span作为Cloud Run端点调用Span的子节点,属于同一Trace层级。

内容的提问来源于stack exchange,提问作者Neil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 03:27:22