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

Cloud Run部署Python gRPC服务OpenTelemetry链路追踪传播失效问题

问题根因

你仅配置了全局传播器,但没有完成gRPC请求的链路上下文提取逻辑,传播器不会自动解析gRPC调用的metadata,因此手动创建的span始终是新链路的根span,和请求头里的trace id无关。


方案1:使用OpenTelemetry gRPC自动埋点(推荐)

该方案不需要修改业务代码,自动完成上下文提取、span创建等操作:

  • 首先安装依赖包:pip install opentelemetry-instrumentation-grpc
  • 在configure_tracing()执行完成后、启动gRPC服务前,添加instrumentation初始化代码:
from opentelemetry.instrumentation.grpc import GrpcInstrumentorServer

grpc_server_instrumentor = GrpcInstrumentorServer()
grpc_server_instrumentor.instrument()
  • 此时不需要在业务代码里手动创建GetStripeInvoice span,instrumentation会自动创建服务端span,且自动关联请求头里的trace id。如果需要自定义子span,直接在方法内创建即可,会自动继承父上下文。

方案2:手动提取链路上下文

如果不想使用自动埋点,你需要在创建span前手动从gRPC metadata中提取父上下文,修改gRPC方法代码如下:

import grpc
from opentelemetry import trace, propagate
import stripe

from common import cloud_logging, datastore_utils, proto_helpers, tracing
from services.payment_service import payment_service_pb2
from third_party import stripe_client

def GetStripeInvoice(
    self, request: payment_service_pb2.GetStripeInvoiceRequest, context: grpc.ServicerContext
) -> payment_service_pb2.StripeInvoiceResponse:

    tracer: trace.Tracer = tracing.get_tracer()
    # 从gRPC metadata中提取链路上下文
    metadata = dict(context.invocation_metadata())
    # 传播器会自动从metadata中读取x-cloud-trace-context字段解析父上下文
    parent_context = propagate.extract(metadata)
    
    # 创建span时传入提取到的父上下文
    with tracer.start_as_current_span('GetStripeInvoice', context=parent_context):
        print(f"trace ID from header: {metadata.get('x-cloud-trace-context')}")
        # 可打印当前span的trace id验证是否匹配
        current_span = trace.get_current_span()
        print(f"current span trace id: {format(current_span.get_span_context().trace_id, '032x')}")
        cloud_logging.info(f"Getting Stripe invoice.")
        order = datastore_utils.get_pb_with_pb_key(request.order)

        try:
            invoice: stripe.Invoice = stripe_client.get_invoice(
                invoice_id=order.stripe_invoice_id
            )
            cloud_logging.info(f"Retrieved Stripe invoice. Amount due: {invoice['amount_due']}")
        except stripe.error.StripeError as e:
            cloud_logging.error(
                f"Failed to retrieve invoice: {e}"
            )
            context.abort(code=grpc.StatusCode.INTERNAL, details=str(e))

        return payment_service_pb2.StripeInvoiceResponse(
            invoice=proto_helpers.create_struct(invoice)
        )

补充配置检查

你当前的configure_tracing方法中,只有非本地环境才设置了全局传播器,如果需要在本地测试链路传播逻辑,需要把propagate.set_global_textmap的配置移到分支外,本地环境也启用CloudTrace格式传播器:

def configure_tracing() -> None:
    trace.set_tracer_provider(sdk_trace.TracerProvider())
    # 全局都设置CloudTrace格式传播器,方便本地测试
    propagate.set_global_textmap(cloud_trace_propagator.CloudTraceFormatPropagator())
    if app_instance.IS_LOCAL:
        print("Configuring local tracing.")
        span_exporter: export.SpanExporter = export.ConsoleSpanExporter()
    else:
        print(f"Configuring cloud tracing in environment {app_instance.ENVIRONMENT}.")
        span_exporter = cloud_trace.CloudTraceSpanExporter()

    trace.get_tracer_provider().add_span_processor(export.SimpleSpanProcessor(span_exporter))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 01:27:02