OpenTelemetry PHP自动插桩
博客文章在发布后不会更新。这篇文章已经发布一年多了,其内容可能已过时,部分链接可能无效。在依赖任何信息之前,请务必核实。
自动检测是指在不修改用户应用程序源代码的情况下为其添加追踪能力的过程。有几种技术可以实现这一点,但它们或多或少都以相同的方式工作,通过在编译时、链接时、运行时注入额外的代码,或者通过扩展操作系统(对于 eBPF)来实现。这篇博文介绍了 OpenTelemetry PHP 自动检测使用的方法。
先决条件
要使用 PHP 自动检测,您需要三样东西:
- PHP 8.0 或更高版本。PHP 自动检测使用了 PHP 8.0 中引入的可观测性 API。
- Composer
- 您的机器上必须安装 C 编译器。
PHP 8.0 可观测性 API 背景
可观测性 API 允许您在不引入其他区域额外性能损失的情况下,注册和执行在原始函数之前和之后运行的额外代码(函数)。在 PHP 8.0 之前,添加追踪能力最常用的技术是修改 zend_execute_ex 函数(一种猴子补丁技术)。然而,这可能导致运行时性能问题、堆栈溢出以及不必要的总体应用程序开销。过去考虑的另一种方法是接入 AST 并在编译时修改它,但没有已知的生产级追踪器使用这种技术。
从自动检测角度看可观测性 API
在撰写本文时,可观测性 API 已被 C 扩展 使用,并公开了一个具有以下接口的函数:
function hook(
?string $class,
string $function,
?\Closure $pre = null,
?\Closure $post = null,
): bool {}
用户应用程序可以使用此函数来实现对观察到的函数执行附加功能。下面的代码片段展示了如何检测 helloWorld 函数。
function helloWorld() {
echo 'helloWorld';
}
\OpenTelemetry\Instrumentation\hook(null, 'helloWorld',
static function (?string $class, array $params, ?string $classname, string $functionname, ?string $filename, ?int $lineno)
{
echo 'before';
},
static function (mixed $object, array $params, mixed $return, ?Throwable $exception)
{
echo 'after';
}
);
同样,我们为 Contrib 存储库中最重要的 接口/库/框架 中的一些实现了追踪支持。每个 自动检测 包都使用上面的 hook 函数来注册和提供追踪功能。还有一件重要的事情尚未提及,那就是用于创建追踪和其他必要组件的 API 和 SDK。这是 opentelemetry-php 主存储库的职责,该存储库是一切的基础。

如何使用
自动检测所需的所有组件都可以手动安装,但我们投入了时间和精力来降低入门门槛,并创建了一个可以为您完成这些工作的安装程序。本节将展示如何自动检测一个从头开始创建的简单 PHP laravel 应用程序。
第一步是创建一个演示应用程序。这里我们使用了流行的 Laravel 框架。
composer create-project laravel/laravel example-app
接下来,安装 opentelemetry-instrumentation-installer。
cd example-app
composer require open-telemetry/opentelemetry-instrumentation-installer
OpenTelemetry instrumentation installer 支持两种模式:
- basic(安装所有组件的最新版本)
- advanced(给予用户控制权)
安装完成后,运行 install-otel-instrumentation 命令,并带上 basic 或 advanced 参数,如下所示。
./vendor/bin/install-otel-instrumentation basic
最后一步是使用 run-with-otel-instrumentation 运行您的应用程序。
./vendor/bin/run-with-otel-instrumentation php -S localhost:8080 -t public public/index.php
run-with-otel-instrumentation 并非魔法:它所做的一切都可以手动完成,只需设置环境变量并正常运行您的应用程序即可。它是一个方便的工具,可以快速地将 OpenTelemetry 应用于具有可正常工作的默认配置的应用程序。
./vendor/bin/run-with-otel-instrumentation php -S localhost:8080 -t public public/index.php
现在,通过触发对 https://:8080 的请求,您应该能在 Jaeger 中看到以下结果。

当前状态和后续步骤
我们已经具备了所有必要的组件:
- API 和 SDK 作为基础,并实现了 OpenTelemetry 规范。
- C 扩展作为自动检测的基础。
- 对大多数重要和流行的库及框架的支持(开发中)的自动检测。
- 开发工具,可以帮助降低用户和有兴趣检测任意代码的开发者的门槛。
- 文档
我们的目标之一是提高对这项工作的认识,并吸引更多人来帮助我们改进它、扩展覆盖范围并修复错误。
请尝试使用并给我们反馈。如果您遇到任何问题,可以提交一个 issue。有疑问?欢迎在 CNCF #otel-php Slack 频道与我们联系,或者参加我们的 SIG 会议,您可以在 OTel 公共日历上找到会议信息。