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

Quarkus集成OpenTelemetry:重定向时链路追踪丢失问题求助

解决方案:自定义OpenTelemetry Propagator 支持Cookie提取traceparent

你的问题核心在于OpenTelemetry的Quarkus集成默认仅从请求头读取traceparent,但第三方重定向只将链路参数放在Cookie中,导致上下文无法自动关联。以下是可行的解决思路:

1. 自定义Cookie感知的Trace Propagator

扩展OpenTelemetry的TextMapPropagator,让它优先从请求头提取链路上下文,若头中不存在则从Cookie读取traceparent:

import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.TextMapGetter;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.context.propagation.TextMapSetter;
import io.opentelemetry.context.propagation.W3CTraceContextPropagator;
import jakarta.ws.rs.core.Cookie;
import jakarta.ws.rs.core.HttpHeaders;
import java.util.Collections;
import java.util.List;
import java.util.Map;

public class CookieAwareTracePropagator implements TextMapPropagator {

    private final W3CTraceContextPropagator delegate = W3CTraceContextPropagator.getInstance();

    @Override
    public List<String> fields() {
        return delegate.fields();
    }

    @Override
    public <C> void inject(Context context, C carrier, TextMapSetter<C> setter) {
        // 保留默认的注入逻辑(将traceparent写入请求头)
        delegate.inject(context, carrier, setter);
    }

    @Override
    public <C> Context extract(Context context, C carrier, TextMapGetter<C> getter) {
        // 先尝试从请求头提取上下文
        Context extractedContext = delegate.extract(context, carrier, getter);

        // 若头中无有效上下文,尝试从Cookie读取
        if (extractedContext == Context.root() && carrier instanceof HttpHeaders headers) {
            Cookie traceCookie = headers.getCookies().get("traceparent");
            if (traceCookie != null) {
                // 构造模拟请求头载体,让W3C Propagator解析Cookie中的traceparent
                Map<String, String> fakeHeaderCarrier = Collections.singletonMap("traceparent", traceCookie.getValue());
                extractedContext = delegate.extract(context, fakeHeaderCarrier, Map::get);
            }
        }
        return extractedContext;
    }
}

2. 在Quarkus中注册自定义Propagator

通过CDI Producer替换默认的Propagator,确保应用启动时生效:

import io.opentelemetry.context.propagation.TextMapPropagator;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import jakarta.enterprise.inject.Specializes;

@ApplicationScoped
public class CustomOtelConfig {

    @Produces
    @Specializes
    public TextMapPropagator customTextMapPropagator() {
        return new CookieAwareTracePropagator();
    }
}

3. 清理冗余代码

移除你之前创建的@ServerRequestFilter和手动创建父Span的代码——自定义Propagator会在请求处理的最早期自动完成上下文关联,后续所有由OTel自动生成或你手动创建的Span都会自动关联到父链路。

关键注意事项

  • 确认第三方重定向后携带的Cookie名称确实是traceparent,如果是自定义名称,需修改代码中对应的Cookie键值。
  • 确保Quarkus与OpenTelemetry依赖版本兼容:Quarkus 3.x对应OTel 1.28+,Quarkus 2.x对应OTel 1.20+,避免版本冲突导致Propagator不生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 02:46:22