应使用jukylin/jaeger-php包,它是当前维护活跃、适配opentracing v1.0、支持b3 propagation且文档清晰的主流选择,安装命令为composer require jukylin/jaeger-php。

composer require 用哪个包?别装错
PHP 生态里有至少三个名字带 “jaeger” 的 Composer 包,但只有 jukylin/jaeger-php 是当前维护活跃、适配 OpenTracing v1.0、支持 B3 Propagation 且文档清晰的主流选择。另一个常见包 jonahgeorge/jaeger-client-php 已多年未更新,不兼容 PHP 8.2+ 的类型声明,jaeger-php(无命名空间)则缺乏采样控制和上下文透传能力。
安装命令必须是:composer require jukylin/jaeger-php
如果项目启用了 minimum-stability: dev,建议显式指定版本避免引入不稳定快照:composer require jukylin/jaeger-php:^2.0
服务名和服务地址写错,Span 就静默丢弃
初始化时传入的服务名不是“随便起个名”,而是 Jaeger UI 分组过滤的唯一依据。写成 my-app-v2 和 my_app_v2 会被视为两个服务,根本搜不到完整链路;含空格或特殊字符会触发 invalid service name 错误导致上报 400。
Agent 地址也必须匹配实际网络可达性:
- 本地开发:用 127.0.0.1:6831(UDP),不是 localhost(某些容器 DNS 解析失败)
- Docker 环境:用宿主网关 IP(如 host.docker.internal:6831)或 Docker 网络别名
- Kubernetes:用 Service 名 + 端口,如 jaeger-agent.default.svc.cluster.local:6831
漏配或连不通时,$span->finish() 不报错,但数据永远发不出去——这是最常被忽略的“无声失败”。
HTTP 中间件里必须手动透传 B3 Header
ThinkPHP、Laravel 或原生 Swoole 都不自动处理分布式上下文,X-B3-TraceId、X-B3-SpanId、X-B3-ParentSpanId 这三组 Header 必须在入口中间件解析,并在下游请求中重新注入,否则链路一跳就断。
关键动作:
- 从 $_SERVER['HTTP_X_B3_TRACEID'] 等读取已有上下文,不存在则生成新 trace_id(推荐 bin2hex(random_bytes(16)))
- 调用 $tracer->startSpan($op, ['child_of' => $spanContext]) 启动子 Span,不能只用 startSpan($op) 创建 root Span
- 发起 Guzzle/curl 请求前,用 $tracer->inject($span->getContext(), \OpenTracing\Formats\TEXT_MAP, $headers) 注入 Header
- 响应返回前,把当前 Span ID 写回响应头,供上游继续传递
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
Span 生命周期管理不当,UI 里看到全是孤岛
一个 Span 对应一个明确的业务单元,不是每个函数调用都要 Start/Finish。常见错误:
- 在 for 循环里反复 startSpan('db-query'),撑爆 Jaeger 存储且无法聚合分析
- defer $span->finish() 但没把带 Span 的 Context 传进 goroutine(Swoole 协程同理),导致子任务新建无父 Span 的 root
- 控制器方法结束才 finish,中间异步日志、消息队列投递等操作脱离 Span 上下文
正确做法:
- 入口 HTTP handler 创建 server-type Span
- 每次 DB 查询、Redis Get、Guzzle 调用单独建 client-type Span,显式设 child_of
- 异步任务启动时,从当前 Span 拷贝 Context 并注入新 Span,而非复用全局 tracer
Span 的嵌套深度、标签粒度、采样率配置,这些细节不会报错,但会让 Jaeger UI 里的调用树失去分析价值——你得盯着火焰图看半天,才发现瓶颈其实藏在第三层 Span 的某个 tag 里。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










