OpenTelemetry PHP¶
OpenTelemetry PHP 通过 PHP 扩展提供运行时 Hook,再由 Composer 安装的框架插桩库生成遥测数据。无需修改业务代码,即可采集受支持的 Web 框架、HTTP 客户端、数据库等调用。
本文使用 DataKit 的 OpenTelemetry 采集器接收 OTLP 数据并转发到观测云:
前置条件¶
- PHP 8.0 或更高版本;
- Composer,以及可安装 PHP 扩展的 PECL 或系统包管理器;
- 应用通过 Composer 加载
vendor/autoload.php; - 已安装 DataKit,且 DataKit 已连接到目标观测云工作空间;
- PHP 应用到 DataKit 的网络可达:OTLP/HTTP 使用 DataKit HTTP 端口
9529,OTLP/gRPC 默认使用4317。
一、开启 OpenTelemetry 采集器¶
进入 DataKit 安装目录下的 conf.d/opentelemetry。如果尚未创建采集器配置,复制示例文件:
确认 opentelemetry.conf 至少包含以下接收配置:
[[inputs.opentelemetry]]
# 将需要在观测云中作为标签保留的自定义属性加入白名单。
customer_tags = ["team", "project"]
[inputs.opentelemetry.http]
http_status_ok = 200
trace_api = "/otel/v1/traces"
metric_api = "/otel/v1/metrics"
logs_api = "/otel/v1/logs"
[inputs.opentelemetry.grpc]
addr = "127.0.0.1:4317"
max_payload = 16777216
接收地址如下:
| 协议 | 数据类型 | DataKit 接收地址 |
|---|---|---|
| OTLP/HTTP + Protobuf | Trace | http://<DataKit-IP>:9529/otel/v1/traces |
| OTLP/HTTP + Protobuf | Metric | http://<DataKit-IP>:9529/otel/v1/metrics |
| OTLP/HTTP + Protobuf | Log | http://<DataKit-IP>:9529/otel/v1/logs |
| OTLP/gRPC | Trace、Metric、Log | http://<DataKit-IP>:4317 |
如果 PHP 应用与 DataKit 不在同一主机,需按实际部署调整 DataKit 监听地址、防火墙或其他网络访问控制。gRPC 可将 addr 改为应用可访问的监听地址,例如 0.0.0.0:4317。不要将 OTLP 接收端口直接暴露到公网。
重启 DataKit 并检查服务:
二、应用接入 OpenTelemetry¶
安装 OpenTelemetry PHP 扩展¶
先确认 PHP CLI 使用的版本和配置文件位置:
准备好 PHP 开发环境、PECL、编译器、make 和 autoconf 后,从 PECL 官方源安装扩展:
在 PHP 扫描的附加配置目录中创建 99-opentelemetry.ini,或把以下配置加入当前 php.ini:
重启 PHP-FPM、Apache 或其他 PHP 应用进程,然后验证扩展:
只安装扩展不会自动产生 Trace,还必须安装 SDK、OTLP exporter 和与应用框架对应的插桩包。
安装 SDK 和自动插桩包¶
以下以 Slim 和 PSR-18 HTTP 客户端为例,在应用的 Composer 项目目录执行:
composer require \
open-telemetry/sdk \
open-telemetry/exporter-otlp \
open-telemetry/opentelemetry-auto-slim \
open-telemetry/opentelemetry-auto-psr18
如果应用中尚无可被 OTLP HTTP exporter 使用的 PSR-17 Factory 和异步 HTTP Client 实现,可补充:
不同框架需要安装不同的 open-telemetry/opentelemetry-auto-* 包。可在 OpenTelemetry PHP 插桩包列表中选择与当前框架、数据库或客户端匹配的包。没有安装对应插桩包的组件不会自动生成 Span。
通过环境变量启动¶
下面以 OTLP/HTTP + Protobuf 为例,默认接入 Trace,Metric 和 Log 暂时关闭:
export OTEL_PHP_AUTOLOAD_ENABLED="true"
export OTEL_SERVICE_NAME="order-service"
export OTEL_RESOURCE_ATTRIBUTES="env=prod,version=1.0.0,team=backend"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="none"
export OTEL_LOGS_EXPORTER="none"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:9529/otel"
export OTEL_PROPAGATORS="tracecontext,baggage"
php -S 0.0.0.0:8080 -t public
OTEL_EXPORTER_OTLP_ENDPOINT 是基础地址。OTLP/HTTP exporter 会根据数据类型自动追加 /v1/traces、/v1/metrics 或 /v1/logs,最终对应 DataKit 的 /otel/v1/* 路由。
PHP-FPM、Apache、Supervisor 或 systemd 不一定继承当前终端的环境变量。应将变量写入实际服务进程的启动环境,或使用下一节的 PHP 配置方式,然后重启服务。
通过 PHP 配置启用¶
也可以将以下内容加入 PHP-FPM 或 Apache 实际加载的 php.ini 或附加 INI 文件:
OTEL_PHP_AUTOLOAD_ENABLED="true"
OTEL_SERVICE_NAME="order-service"
OTEL_RESOURCE_ATTRIBUTES="env=prod,version=1.0.0,team=backend"
OTEL_TRACES_EXPORTER="otlp"
OTEL_METRICS_EXPORTER="none"
OTEL_LOGS_EXPORTER="none"
OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:9529/otel"
OTEL_PROPAGATORS="tracecontext,baggage"
PHP CLI 和 PHP-FPM 可能加载不同的配置文件。使用 php --ini 只能确认 CLI 配置;接入 Web 应用时,还需确认 PHP-FPM 或 Apache 对应 SAPI 已加载扩展和以上配置。
使用 OTLP/gRPC¶
PHP 使用 OTLP/gRPC 还需要 grpc PHP 扩展和 Composer transport 包:
sudo pecl install grpc
composer require open-telemetry/transport-grpc
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:4317"
gRPC endpoint 不能追加 /v1/traces 等 HTTP 路径。
三、数据上报参数¶
基础参数¶
| 环境变量 | 说明 | 建议值或示例 |
|---|---|---|
OTEL_SERVICE_NAME |
设置 service.name;未设置时服务无法被稳定识别。 |
order-service,生产环境必须显式设置。 |
OTEL_RESOURCE_ATTRIBUTES |
资源属性,格式为逗号分隔的 key=value。 |
env=prod,version=1.0.0,team=backend |
OTEL_TRACES_EXPORTER |
Trace 导出器。 | 上报到 DataKit 时设为 otlp;关闭时设为 none。 |
OTEL_METRICS_EXPORTER |
Metric 导出器。 | 需要上报指标时设为 otlp,否则设为 none。 |
OTEL_LOGS_EXPORTER |
Log 导出器。 | 需要上报日志时设为 otlp,否则设为 none。 |
OTEL_PROPAGATORS |
跨服务上下文传播格式。 | 默认 tracecontext,baggage;全链路应保持兼容。 |
OTEL_SDK_DISABLED |
禁用 OpenTelemetry SDK。 | 默认 false;应急关闭时设为 true。 |
service.name 用于观测云中的服务归属;建议同时设置 env 和 version,用于按环境和版本筛选。其他自定义资源属性需要加入 DataKit customer_tags 白名单后才会作为标签保留,属性名中的 . 会转换为 _。
PHP 自动插桩参数¶
| 环境变量 | 说明 | 默认值或示例 |
|---|---|---|
OTEL_PHP_AUTOLOAD_ENABLED |
启用 SDK 和自动插桩的 Composer 自动加载。 | 默认 false;零代码接入必须设为 true。 |
OTEL_PHP_DISABLED_INSTRUMENTATIONS |
禁用指定的已安装插桩,多个名称用逗号分隔;也可使用 all。 |
psr15,psr18 |
OTEL_PHP_EXCLUDED_URLS |
不加载 SDK 的请求 URL 正则表达式,多个表达式用逗号分隔。 | healthz,readyz |
OTEL_PHP_LOG_DESTINATION |
OpenTelemetry PHP 内部错误和告警的输出位置。 | stderr、error_log、none 等。 |
OTEL_PHP_FIBERS_ENABLED |
启用 Fiber 上下文存储;非 CLI SAPI 还需额外预加载配置。 | 默认 false。 |
OTLP 参数¶
| 环境变量 | 说明 | 建议值或示例 |
|---|---|---|
OTEL_EXPORTER_OTLP_PROTOCOL |
所有信号的 OTLP 协议。 | DataKit 支持 http/protobuf 或 grpc。 |
OTEL_EXPORTER_OTLP_ENDPOINT |
所有信号共用的基础地址。 | HTTP:http://datakit-host:9529/otel;gRPC:http://datakit-host:4317。 |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT |
仅 Trace 使用的地址,优先于共用地址。 | http://datakit-host:9529/otel/v1/traces |
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT |
仅 Metric 使用的地址,优先于共用地址。 | http://datakit-host:9529/otel/v1/metrics |
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT |
仅 Log 使用的地址,优先于共用地址。 | http://datakit-host:9529/otel/v1/logs |
OTEL_EXPORTER_OTLP_HEADERS |
所有 OTLP 请求携带的请求头,多个值用逗号分隔。 | x-tenant=tenant-a;需与 DataKit expected_headers 一致。 |
OTEL_EXPORTER_OTLP_COMPRESSION |
OTLP 请求压缩方式。 | 安装 zlib 扩展后可设为 gzip。 |
OTEL_EXPORTER_OTLP_TIMEOUT |
单次导出超时,单位毫秒。 | 10000 |
DataKit 的 OTLP/HTTP 采集仅支持 Protobuf,请使用 http/protobuf,不要使用 http/json。统一 endpoint 与某类数据的 endpoint 同时存在时,某类数据的配置优先。
采样参数¶
| 环境变量 | 说明 | 默认值或示例 |
|---|---|---|
OTEL_TRACES_SAMPLER |
Trace 头部采样器。 | 默认 parentbased_always_on;按比例采样使用 parentbased_traceidratio。 |
OTEL_TRACES_SAMPLER_ARG |
采样器参数。 | 0.1 表示根 Trace 采样 10%。 |
生产环境应根据流量和数据预算设置采样率。应用侧头部采样与 DataKit 侧采样同时开启时,最终保留率会叠加降低,应统一规划采样位置。
验证接入¶
请求一个已安装自动插桩包的应用路由,然后在 DataKit 主机检查接收日志:
出现 /otel/v1/traces 的 POST 请求且响应码为 200,表示 DataKit 已接收 Trace。然后进入观测云的「应用性能监测 > 链路」按 service:order-service 查询。
如果没有数据,依次检查:PHP Web SAPI 是否加载 opentelemetry 扩展、应用是否加载 Composer autoloader、OTEL_PHP_AUTOLOAD_ENABLED 是否为 true、是否安装了与实际代码路径匹配的自动插桩包,以及 OTLP endpoint 是否可达。