composer本身不提供链路透传能力,它仅负责依赖安装;真正实现traceparent透传的是引入的sdk(如jukylin/jaeger-php或open-telemetry/opentelemetry),需显式注册w3c propagator、包装httplug兼容http客户端、并在请求入口绑定上下文生命周期。

Composer 本身不提供链路透传能力,它只是把代码拉下来;真正实现透传的是你引入的 SDK(比如 jukylin/jaeger-php 或 open-telemetry/opentelemetry),而这些 SDK 要生效,必须显式绑定上下文传播逻辑,否则 traceparent header 不会被注入或提取,Span 就断了。
为什么装了包却没透传 traceparent?
常见现象是执行了 composer require jukylin/jaeger-php 或 composer require open-telemetry/opentelemetry,但下游服务收不到 traceparent header。这不是 Composer 的问题,而是 SDK 没被正确接入 HTTP 生命周期。
- HTTP 客户端未包装:直接用
new GuzzleHttp\Client()不会自动注入 header;必须走 HTTPlug 兼容层(如php-http/guzzle7-adapter)并启用中间件 - 初始化时机错误:TracerProvider 或 GlobalTracer 在 CLI 或 Worker 启动时初始化,但没在每次请求开始时 reset 或绑定 request context
- 手动埋点遗漏 extract:PHP-FPM 下,
$_SERVER['HTTP_TRACEPARENT']需在入口处调用$tracer->extract(Formats\HTTP_HEADERS, $_SERVER),否则 Span 默认为 root - W3C propagator 未启用:OpenTelemetry 默认用
TraceContextPropagator,但若没显式设置Propagator::setGlobalPropagator(new TraceContextPropagator()),header 就不会读写
如何让 Composer 引入的 SDK 真正支持透传?
关键不是“装什么”,而是“怎么接”。以 open-telemetry/opentelemetry 为例,透传依赖三件事:propagator 注册、HTTP client 包装、Span 生命周期与请求对齐。
- 必须在请求入口(如 PSR-15 middleware 或框架 boot 阶段)调用
Propagator::setGlobalPropagator(new TraceContextPropagator()) - HTTP 请求必须经由 HTTPlug client:用
Http\Client\Curl\Client替代原生 cURL;用Http\Adapter\Guzzle7\Client替代GuzzleHttp\Client - Span 必须 start → inject → finish 成对出现:startSpan 后要主动调用
$span->getSpanContext()->getTraceId()验证是否非空,避免 tracer 为 null 导致静默失败 - 不要复用全局 Tracer 实例:PHP-FPM 下每个请求应 new 一个
TracerProvider或至少重置其 internal state,否则跨请求 context 泄漏
自封装组件时最容易踩的坑
自己写一个基于 Composer 的透传 wrapper(比如叫 mycompany/trace-middleware),核心风险不在逻辑,而在加载顺序和作用域。
-
composer dump-autoload -o必须执行:否则 PSR-4 自动加载失效,use OpenTelemetry\SDK\Trace\TracerProvider会报 Class not found - 不能在
config/app.php(Laravel)或bootstrap.php(ThinkPHP)里直接 new TracerProvider:它依赖$_SERVER,必须延迟到 request 初始化后 - 别把
traceparent当字符串硬编码处理:必须用Propagation\TextMapCarrier接口抽象 carrier,否则无法兼容 Baggage 或其他 propagator - 测试时别只 mock
$_SERVER:真实环境里 Nginx/Apache 可能过滤掉带下划线的 header,需确保fastcgi_param HTTP_TRACEPARENT $http_traceparent已配置
透传不是“装完就跑”,它卡在初始化时机、HTTP client 封装深度、以及 context 生命周期管理三个交点上;任何一个环节松动,traceparent 就像没系牢的鞋带,走两步就掉了。











