Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

gRPC server instrumentations (grpc-1.5, armeria-grpc) don't make extracted W3C baggage current in the handler

未关闭
#12,654 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 2 天内回复

还没有人认领这个 Issue。

评估

难度
3/5
预计耗时
1-2 天
新手友好度
78/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
grpc, java
领域
observability

调研方向

Start with the extraction and activation paths in dd-java-agent/instrumentation/grpc-1.5/.../TracingServerInterceptor.java and the corresponding armeria-grpc-0.84 file, then run the GrpcServerBaggageTest reproduction. Compare them with HttpServerDecorator and JettyServerAdvice; done means inbound baggage is current in the unary handler and is reinjected on outbound calls while trace propagation still works.

由索引模型根据 Issue 内容生成。

描述

comp: context propagation inst: grpc type: feature request
Tracer Version(s)

1.56.0, 1.66.0 (observed); master at 02d50d2 (code reading)

Java Version(s)

17.0.13

JVM Vendor

Eclipse Adoptium / Temurin

Bug Report

gRPC server instrumentations (grpc-1.5 and armeria-grpc-0.84) extract inbound W3C baggage but don't make it current while the service runs. As a result:

  • Baggage.current() (OTel API, DD_TRACE_OTEL_ENABLED=true) is empty inside the handler.
  • Downstream calls from the handler carry no baggage header, even though the trace context (x-datadog-*, traceparent) propagates fine.

The baggage.* span tags still show up on the grpc.server span, which makes the loss easy to miss.

Root cause. Both TracingServerInterceptors call the deprecated AgentPropagation.extractContextAndGetSpanContext (internal-api, v1.66.0 L33-L38).

  • That helper extracts the full Context and then returns only the span context, so the extracted Baggage element is discarded.
  • The interceptor then runs next.startCall(...) and every listener callback under activateSpan(span), which is a span-only context.
  • The tags appear anyway because BaggagePropagator.extract also copies the baggage onto the extracted TagContext (v1.66.0 L130-L138).

Call sites:

HTTP servers don't have this problem. They were moved to full-context extraction in #8820: HttpServerDecorator.extract returns the whole Context, and e.g. JettyServerAdvice attaches parentContext.with(span) (v1.66.0 L32-L61).

Observed (dd-java-agent 1.56.0 and 1.66.0; Armeria 1.33.4 and 1.41.0). An agent-less client sends baggage: jtbd=ap.curl,user.id=u1 plus x-datadog-* headers to a relay server, whose handler logs Baggage.current() and makes one outbound OkHttp call:

relay server Baggage.current() in handler (OTel bridge on) baggage header on the relay's outbound call baggage.jtbd tag on server span trace joins
Armeria GrpcService {} none yes yes
Jetty 11 servlet {jtbd=ap.curl, user.id=u1} jtbd=ap.curl,user.id=u1 yes yes

The result was the same with the OTel bridge unset, apart from the Baggage.current() column, which the bridge feeds. I did not run a grpc-java (Netty) server in that harness. For grpc-1.5, the unit test below reproduces the same loss.

Other callers of the deprecated helper (master at 02d50d2, non-test code). I found these by reading the code and have not reproduced them. They look like they have the same shape: extract, keep only the span context, then activate a span-only context.

  • RPC: sofarpc-5.0 (ProviderProxyInvokerInstrumentation)
  • Messaging consumers: kafka-clients-0.11 and kafka-clients-3.8 (TracingIterator), aws-java-sqs-1.0 and aws-java-sqs-2.0 (TracingIterator), javax-jms-1.1 (JMSMessageConsumerInstrumentation, DatadogMessageListener), rabbitmq-amqp-2.7 (RabbitDecorator), google-pubsub-1.116 (PubSubDecorator)
  • API shims: opentracing-0.31 / 0.32 (OTTracer), opentelemetry-0.3 (OtelContextPropagators)

I've seen #11286 and the note there that W3C baggage was initially scoped to HTTP. gRPC carries baggage as an HTTP/2 header, and these servers already extract and tag it, so it seemed worth reporting on its own. Please relabel as a feature request if that fits your conventions better.

Expected Behavior

When a gRPC server span is started from extracted headers, the rest of the extracted context (W3C baggage) is current for the whole call, as it is for HTTP servers. In particular:

  • Baggage.current() in the service implementation returns the inbound members.
  • Outbound calls made from the handler re-inject the baggage header.
Reproduction Code

Minimal Spock test against grpc-1.5. The same shape against an Armeria GrpcService fails the same way.

class GrpcServerBaggageTest extends InstrumentationSpecification {
  def "inbound baggage is current in unary handler"() {
    setup:
    Map<String, String> seen = null
    def greeter = new GreeterGrpc.GreeterImplBase() {
        @Override
        void sayHello(Helloworld.Request req, StreamObserver<Helloworld.Response> obs) {
          seen = Baggage.fromContext(Context.current())?.asMap()
          obs.onNext(Helloworld.Response.newBuilder().setMessage("hi").build())
          obs.onCompleted()
        }
      }
    def name = InProcessServerBuilder.generateName()
    def server = InProcessServerBuilder.forName(name).addService(greeter).directExecutor().build().start()
    def md = new Metadata()
    md.put(Metadata.Key.of("baggage", Metadata.ASCII_STRING_MARSHALLER), "user.id=abc123")
    def channel = InProcessChannelBuilder.forName(name)
      .intercept(MetadataUtils.newAttachHeadersInterceptor(md)).directExecutor().build()

    when:
    GreeterGrpc.newBlockingStub(channel).sayHello(Helloworld.Request.newBuilder().setName("x").build())

    then:
    seen == ["user.id": "abc123"]   // on master: seen == null (a span is current, baggage is not)

    cleanup:
    channel.shutdownNow(); server.shutdownNow()
  }
}
主要语言
Java
星标
737
派生
361
平均合并
3 天 13 小时
30 天内合并 PR
171

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

DataDog/dd-trace-java 的其他 Issue

查看 DataDog/dd-trace-java 的全部 Issue

相似的 Issue

更多 Java Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。