通过 OpenTelemetry-PHP 接入 PHP 应用(推荐)

最近更新时间: 2026-06-30 15:06:00

说明:

  • OpenTelemetry 是工具、API 和 SDK 的集合,用来检测、生成、收集和导出遥测数据(指标、日志和跟踪),帮助用户分析软件的性能和行为。关于 OpenTelemetry 的更多信息请参考 OpenTelemetry 官方网站
  • OpenTelemetry 社区活跃,技术更迭迅速,广泛兼容主流编程语言、组件与框架,为云原生微服务以及容器架构的链路追踪能力广受欢迎。

本文将通过相关操作介绍如何通过社区的 OpenTelemetry-PHP 方案接入 PHP 应用。
OpenTelemetry-PHP 方案对于 PHP 系的常用依赖库和框架,例如 Slim 等,提供了自动埋点,在不需要修改代码的情况下就能实现链路信息的上报。其他支持自动埋点的依赖库和框架请参考 OpenTelemetry 社区提供的 完整列表

前提条件

安装如下工具:

  • PECL
  • composer
    并确保 shell 中可以运行以下命令:
php -v
composer -v

自动接入

手动接入

PHP 7.4+

Demo 应用

示例代码 index.php 是一个 HTTP Server 使用 PDO 连接 MySQL 数据库数据库操作,对应的 MySQL 务请自行搭建,或直接创建云产品实例。

  1. 初始化应用

    mkdir <project-name> && cd <project-name>
    
    composer init \
     --no-interaction \
     --stability beta \
     --require slim/slim:"^4" \
     --require slim/psr7:"^1"
    composer update
    
  2. 编写业务代码
    在目录下创建一个index.php文件,添加如下内容。
    以下内容将使用一个 HTTP Server 接口模拟使用 PDO 连接 MySQL 进行一次搜索操作。

    <?php
    use Psr\Http\Message\ResponseInterface as Response;
    use Psr\Http\Message\ServerRequestInterface as Request;
    use Slim\Factory\AppFactory;
    
    require __DIR__ . '/vendor/autoload.php';
    
    $app = AppFactory::create();
    
    $app->get('/getID', function (Request $request, Response $response) {
    
        $dbms = 'mysql';         // 数据库类型
        $host = 'localhost';     // 数据库主机名
        $dbName = 'Mydb';        // 使用的数据库
        $user = 'root';          // 数据库连接用户名
        $pass = '';              // 对应的密码
        $dsn = "$dbms:host=$host;dbname=$dbName";
    
        try {
            $dbh = new PDO($dsn, $user, $pass); // 初始化一个PDO对象
            echo "连接成功<br/>";
    
            foreach ($dbh->query('SELECT id from userInfo') as $row) {
                $response->getBody()->write($row[0] . "<br/>");
            }
    
            $dbh = null;
        } catch (PDOException $e) {
            die ("Error!: " . $e->getMessage() . "<br/>");
        }
    
        return $response;
    });
    
    $app->run();
    

前置步骤:获取接入点和 Token

  1. 在左侧菜单栏中选择应用性能监控 > 应用监控,单击应用列表 > 接入应用
  2. 在右侧弹出的数据接入抽屉框中,单击 PHP 语言。
  3. 接入 PHP 应用页面,选择您所要接入的地域以及业务系统
  4. 选择接入协议类型OpenTelemetry
  5. 上报方式选择您所想要的上报方式,获取您的接入点Token

    说明:

    • 内网上报:使用此上报方式,您的服务需运行在云平台 VPC。通过 VPC 直接联通,在避免外网通信的安全风险同时,可以节省上报流量开销。
    • 外网上报:当您的服务部署在本地或非云平台 VPC 内,可以通过此方式上报数据。请注意外网通信存在安全风险,同时也会造成一定上报流量。

自动接入方案 (推荐)

步骤1:构建 OpenTelemetry PHP Extension

说明:

如果已经构建过 OpenTelemetry PHP extension,可跳过当前步骤。

  1. 下载构建 OpenTelemetry PHP extension 所需要的工具:
  • macOS

    brew install gcc make autoconf
    
  • Linux(apt)

    sudo apt-get install gcc make autoconf
    
  1. 使用 PECL 构建 OpenTelemetry PHP 扩展:

    pecl install opentelemetry
    

    注意:

    构建成功时输出内容的最后几行如下(路径可能不完全一致):

    Build process completed successfully
    Installing '/opt/homebrew/Cellar/php/8.2.8/pecl/2020829/opentelemetry.so'
    install ok: channel://pecl.php.net/opentelemetry-1.0.3
    Extension opentelemetry enabled in php.ini

  2. 启用 OpenTelemetry PHP 扩展。

    说明:

    如果上一步输出了Extension opentelemetry enabled in php.ini,表明已经启用,请跳过当前步骤。

    php.ini文件中添加如下内容:

    [opentelemetry]
    extension=opentelemetry.so
    

    php.ini文件可能存在的位置:

    OS PATH
    Linux /etc/php.ini
    /usr/bin/php5/bin/php.ini
    /etc/php/php.ini
    /etc/php5/apache2/php.ini
    Mac OSX /private/etc/php.ini
    Windows (with XAMPP installed) C:/xampp/php/php.ini
  3. 验证是否构建并启用成功。

  • 方法一:

    php -m | grep opentelemetry
    

    预期输出:

    opentelemetry
    
  • 方法二:

    php --ri opentelemetry
    

    预期输出:

    opentelemetry
    opentelemetry support => enabled
    extension version => 1.0.3
    
  1. 为应用添加 OpenTelemetry PHP 自动埋点需要的额外依赖。

    pecl install grpc # 这一步构建时间较长
    
    composer require \
      open-telemetry/sdk \
      open-telemetry/exporter-otlp \
      open-telemetry/transport-grpc \
      php-http/guzzle7-adapter \
      open-telemetry/opentelemetry-auto-slim \
      open-telemetry/opentelemetry-auto-pdo
    
  • open-telemetry/sdk:OpenTelemetry PHP SDK。
  • open-telemetry/exporter-otlp:OpenTelemetry PHP OTLP 协议数据上报所需的依赖。
  • open-telemetry/opentelemetry-auto-slim:OpenTelemetry PHP 针对 Slim 框架实现的自动埋点包。
  • open-telemetry/opentelemetry-auto-pdo:OpenTelemetry PHP 针对 PHP DataObject 实现的自动埋点包。

    说明:

    这里导入 open-telemetry/opentelemetry-auto-slimopen-telemetry/opentelemetry-auto-pdo 包是因为示例 demo 中使用了 PDO 和 Slim 框架,可以根据具体业务进行调整。如果业务中组件需要 OpenTelemetry 自动埋点,需要在项目中导入对应的自动埋点包,自动埋点包导入方式具体详情请参见 OpenTelemetry 官方文档

步骤2:运行应用

  1. 执行以下命令:

    env OTEL_PHP_AUTOLOAD_ENABLED=true \
     OTEL_TRACES_EXPORTER=otlp \
     OTEL_METRICS_EXPORTER=none \
     OTEL_LOGS_EXPORTER=none \
     OTEL_EXPORTER_OTLP_PROTOCOL=grpc \
     OTEL_EXPORTER_OTLP_ENDPOINT=<endpoint> \ # 此处替换成步骤1中获得的接入点
     OTEL_RESOURCE_ATTRIBUTES="service.name=<service-name>,token=<token>" \ # 此处<service-name>改为自定义服务名,<token>替换成步骤1中获得的token
     OTEL_PROPAGATORS=baggage,tracecontext \
     php -S localhost:8080
    
  2. 在浏览器中访问以下链接:

    http://localhost:8080/getID
    

    每次进入该页面,OpenTelemetry 都会自动创建 Trace,并将链路数据上报至 APM。

接入验证

启动 PHP 应用后,通过8080端口访问对应的接口,例如 https://localhost:8080/getID。在有正常流量的情况下,应用性能监控 > 应用监控 > 应用列表 中将展示接入的应用,应用性能监控 > 应用监控 > 应用详情 > 实例监控中将展示接入的应用实例。由于可观测数据的处理存在一定延时,如果接入后在控制台没有查询到应用或实例,请等待30秒左右。

自定义埋点(可选)

当自动埋点不满足您的场景或者需要增加业务层埋点时,您可参照下述内容,使用 OpenTelemetry PHP SDK 添加自定义埋点。本文仅展示最基本的自定义埋点方式,OpenTelemetry 社区提供了更多灵活的自定义埋点方式,具体使用方法可参考 OpenTelemetry 社区提供的 PHP 自定义埋点文档

<?php

use OpenTelemetry\API\Globals; // 必须的包

require __DIR__ . '/vendor/autoload.php';
function wait(): void
{
    // 通过Globals包获取当前已经配置的providers
    $tracerProvider = Globals::tracerProvider();
    $tracer = $tracerProvider->getTracer(
        'instrumentation-scope-name', //name (required)
        'instrumentation-scope-version', //version
        'http://example.com/my-schema', //schema url
        ['foo' => 'bar'] //attributes
    );
    
    // 自定义埋点
    $span = $tracer->spanBuilder("wait")->startSpan();
    
    // 业务代码
    sleep(5);
    
    // 自定义埋点结束
    $span->end();
}

wait();

手动接入方案

若 PHP 应用版本不能满足8.0+,但能满足7.4+,可以选择手动埋点上报。本文仅展示最基本的手动埋点方式,OpenTelemetry 社区提供了更多灵活的手动埋点方式,具体使用方法可参考 OpenTelemetry 社区提供的 PHP 手动接入文档

导入 OpenTelemetry PHP SDK 以及 OpenTelemetry gRPC Explorer 所需依赖

  1. 下载 PHP HTTP 客户端库,用于链路数据上报。

    composer require guzzlehttp/guzzle
    
  2. 下载 OpenTelemetry PHP SDK。

    composer require \
     open-telemetry/sdk \
     open-telemetry/exporter-otlp
    
  3. 下载使用 gRPC 上报数据时所需依赖。

    pecl install grpc # 如果之前已经下载过grpc,可以跳过这一步
    composer require open-telemetry/transport-grpc
    

编写 OpenTelemetry 初始化工具类

index.php文件所在目录中创建opentelemetry_util.php文件。并在文件中添加如下代码:

<?php
// 包含设置应用名、Trace导出方式、Trace上报接入点,并创建全局TraceProvide

use OpenTelemetry\API\Globals;
use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator;
use OpenTelemetry\Contrib\Otlp\SpanExporter;
use OpenTelemetry\SDK\Common\Attribute\Attributes;
use OpenTelemetry\SDK\Common\Export\Stream\StreamTransportFactory;
use OpenTelemetry\SDK\Resource\ResourceInfo;
use OpenTelemetry\SDK\Resource\ResourceInfoFactory;
use OpenTelemetry\SDK\Sdk;
use OpenTelemetry\SDK\Trace\Sampler\AlwaysOnSampler;
use OpenTelemetry\SDK\Trace\Sampler\ParentBased;
use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
use OpenTelemetry\SDK\Trace\SpanProcessor\BatchSpanProcessorBuilder;
use OpenTelemetry\SDK\Trace\TracerProvider;
use OpenTelemetry\SemConv\ResourceAttributes;
use OpenTelemetry\Contrib\Grpc\GrpcTransportFactory;
use OpenTelemetry\Contrib\Otlp\OtlpUtil;
use OpenTelemetry\API\Signals;

// OpenTelemetry 初始化配置(需要在PHP应用初始化时就进行OpenTelemetry初始化配置)
function initOpenTelemetry()
{ 
  // 1. 设置 OpenTelemetry 资源信息
  $resource = ResourceInfoFactory::emptyResource()->merge(ResourceInfo::create(Attributes::create([
  ResourceAttributes::SERVICE_NAME => '<your-service-name>', // 应用名,必填,如php-opentelemetry-demo
  ResourceAttributes::HOST_NAME => '<your-host-name>' // 主机名,选填
  'token' => '<your-token>' // 替换成步骤1中获得的 Token
  ])));
  
  
  // 2. 创建将 Span 输出到控制台的 SpanExplorer
  // $spanExporter = new SpanExporter(
  // (new StreamTransportFactory())->create('php://stdout', 'application/json')
  // );
  
  // 2. 创建通过 gRPC 上报 Span 的 SpanExplorer
  $transport = (new GrpcTransportFactory())->create('<grpc-endpoint>' . OtlpUtil::method(Signals::TRACE)); # 替换成步骤1中获得的接入点信息
  $spanExporter = new SpanExporter($transport);
  
  
  // 3. 创建全局的 TraceProvider,用于创建 tracer
  $tracerProvider = TracerProvider::builder()
  ->addSpanProcessor(
  (new BatchSpanProcessorBuilder($spanExporter))->build()
  )
  ->setResource($resource)
  ->setSampler(new ParentBased(new AlwaysOnSampler()))
  ->build();
  
  Sdk::builder()
  ->setTracerProvider($tracerProvider)
  ->setPropagator(TraceContextPropagator::getInstance())
  ->setAutoShutdown(true) // PHP 程序退出后自动关闭 tracerProvider,保证链路数据都被上报
  ->buildAndRegisterGlobal(); // 将 tracerProvider 添加到全局

}
?>

修改应用代码,使用 OpenTelemetry API 创建 Span

  1. index.php文件中导入所需包:

    <?php
    
    use OpenTelemetry\API\Globals;
    use OpenTelemetry\API\Trace\StatusCode;
    use OpenTelemetry\API\Trace\SpanKind;
    use OpenTelemetry\SDK\Common\Attribute\Attributes;
    use OpenTelemetry\SDK\Trace\TracerProvider;
    
    use Psr\Http\Message\ResponseInterface as Response;
    use Psr\Http\Message\ServerRequestInterface as Request;
    use Slim\Factory\AppFactory;
    
    require __DIR__ . '/opentelemetry_util.php';
    
  2. 调用initOpenTelemetry方法完成初始化,需要在 PHP 应用初始化时就进行 OpenTelemetry 初始化配置:

    // OpenTelemetry 初始化,包含设置应用名、Trace导出方式、Trace上报接入点,并创建全局TraceProvider
    initOpenTelemetry();
    
  3. rolldice接口中创建 Span。

    /**
     * 1. 接口功能:模拟扔骰子,返回一个1-6之间的随机正整数
     * 并演示如何创建Span、设置属性、事件、带有属性的事件
     */
    $app->get('/rolldice', function (Request $request, Response $response) {
     // 获取 tracer
     $tracer = \OpenTelemetry\API\Globals::tracerProvider()->getTracer('my-tracer');
     // 创建 Span; 设置span kind,不设置默认为KIND_INTERNAL
     $span = $tracer->spanBuilder("/rolldice")->setSpanKind(SpanKind::KIND_SERVER)->startSpan();
     // 为 Span 设置属性
     $span->setAttribute("http.method", "GET");
     // 为 Span 设置事件
     $span->addEvent("Init");
     // 设置带有属性的事件
     $eventAttributes = Attributes::create([
     "key1" => "value",
     "key2" => 3.14159,
     ]);
    
     // 业务代码
     $result = random_int(1,6);
     $response->getBody()->write(strval($result));
    
     $span->addEvent("End");
     // 销毁 Span
     $span->end();
    
     return $response;
    });
    
  4. 创建嵌套 Span。
    新建一个rolltwodices接口,模拟扔两个骰子,返回两个1-6之间的随机正整数。以下代码演示如何创建嵌套的 Span:

    $app->get('/rolltwodices', function (Request $request, Response $response) {
     // 获取 tracer
     $tracer = \OpenTelemetry\API\Globals::tracerProvider()->getTracer('my-tracer');
     // 创建 Span
     $parentSpan = $tracer->spanBuilder("/rolltwodices/parent")->setSpanKind(SpanKind::KIND_SERVER)->startSpan();
     $scope = $parentSpan->activate();
    
     $value1 = random_int(1,6);
    
     $childSpan = $tracer->spanBuilder("/rolltwodices/parent/child")->startSpan();
     
     // 业务代码
     $value2 = random_int(1,6);
     $result = "dice1: " . $value1 . ", dice2: " . $value2; 
    
     // 销毁 Span
     $childSpan->end();
     $parentSpan->end();
     $scope->detach();
    
     $response->getBody()->write(strval($result));
     return $response;
    });
    
  5. 使用 Span 记录代码中发生的异常。
    新建error接口,模拟接口发生异常。以下代码演示如何在代码发生异常时使用 Span 记录状态:

    $app->get('/error', function (Request $request, Response $response) {
     // 获取 tracer
     $tracer = \OpenTelemetry\API\Globals::tracerProvider()->getTracer('my-tracer');
     // 创建 Span
     $span3 = $tracer->spanBuilder("/error")->setSpanKind(SpanKind::KIND_SERVER)->startSpan();
     try {
     // 模拟代码发生异常
     throw new \Exception('exception!');
     } catch (\Throwable $t) {
     // 设置Span状态为error
     $span3->setStatus(\OpenTelemetry\API\Trace\StatusCode::STATUS_ERROR, "expcetion in span3!");
     // 记录异常栈轨迹
     $span3->recordException($t, ['exception.escaped' => true]);
     } finally {
     $span3->end();
     $response->getBody()->write("error");
     return $response;
     }
    });
    

运行应用

  1. 执行以下命令:

    php -S localhost:8080
    
  2. 在浏览器中访问以下链接:

    http://localhost:8080/rolldice
    http://localhost:8080/rolltwodices
    http://localhost:8080/error
    

    每次访问页面,OpenTelemetry 会创建链路数据,并将链路数据上报至 APM。

接入验证

启动 PHP 应用后,通过8080端口访问对应的接口,例如 https://localhost:8080/getID。在有正常流量的情况下,应用性能监控 > 应用监控 > 应用列表 中将展示接入的应用,应用性能监控 > 应用监控 > 应用详情 > 实例监控 中将展示接入的应用实例。由于可观测数据的处理存在一定延时,如果接入后在控制台没有查询到应用或实例,请等待30秒左右。