注意:说明:
一、前提条件
安装如下工具:
·PECL
·composer
并确保 shell 中可以运行以下命令:
php -vcomposer -v
二、自动接入
·PHP 8.0+
·目前自动埋点支持的框架列表详情请参见 OpenTelemetry 产品文档。
三、手动接入
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. 编写业务代码。
在<project-name>目录下创建一个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. 在左侧菜单栏中选择应用性能监控 > 应用列表,单击接入应用。
3. 在右侧弹出的接入应用抽屉框中,单击 PHP 语言。
4. 在接入 PHP 应用页面,选择你所要接入的地域以及业务系统。
5. 选择接入协议类型为 OpenTelemetry。
6. 选择你所想要的上报方式,获取你的接入点和 Token。
注意:说明:
七、步骤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
2. 使用 PECL 构建 OpenTelemetry PHP 扩展。
pecl install opentelemetry
注意:构建成功时输出内容的最后几行如下(路径可能不完全一致)。
注意:Build process completed successfullyInstalling '/opt/homebrew/Cellar/php/8.2.8/pecl/2020829/opentelemetry.so'install ok: channel://pecl.php.net/opentelemetry-1.0.3Extension opentelemetry enabled in php.ini
3. 启用 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 |
4. 验证是否构建并启用成功。
·方法一:
php -m | grep opentelemetry
预期输出:
opentelemetry
·方法二:
php –ri opentelemetry
预期输出:
opentelemetryopentelemetry support => enabledextension version => 1.0.3
5. 为应用添加 OpenTelemetry PHP 自动埋点需要的额外依赖。
pecl install grpc # 这一步构建时间较长composer config allow-plugins.php-http/discovery falsecomposer 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-slim 和 open-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端口访问对应的接口,例如 http://localhost:8080/getID。在有正常流量的情况下,应用性能监控 > 应用列表 中将展示接入的应用,单击应用名称/ID 进入应用详情页。
然后选择实例分析,即可看到接入的应用实例。由于可观测数据的处理存在一定延时,如果接入后在控制台没有查询到应用或实例,请等待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();
十一、自动接入常见问题
如果自动接入后,但是控制台上依然没有看到监控数据,请按以下流程排查。
十二、检查网络
登录业务 Pod,使用 telnet 工具测试与步骤1中获得的接入点网络的连通性。连接成功如下:
若未成功,可尝试外网上报,或尝试解决网络连通问题。
十三、检查 PHP 版本
自动接入需要 PHP 8.0+。
十四、检查环境变量
在 PHP 项目的启动目录输入以下命令,检查在 PHP 启动目录下各环境变量是否设置成功。
echo -e "\\nOTEL_PHP_AUTOLOAD_ENABLED=$OTEL_PHP_AUTOLOAD_ENABLEDOTEL_TRACES_EXPORTER=$OTEL_TRACES_EXPORTEROTEL_METRICS_EXPORTER=$OTEL_METRICS_EXPORTEROTEL_LOGS_EXPORTER=$OTEL_LOGS_EXPORTEROTEL_EXPORTER_OTLP_PROTOCOL=$OTEL_EXPORTER_OTLP_PROTOCOLOTEL_EXPORTER_OTLP_ENDPOINT=$OTEL_EXPORTER_OTLP_ENDPOINTOTEL_RESOURCE_ATTRIBUTES=$OTEL_RESOURCE_ATTRIBUTESOTEL_PROPAGATORS=$OTEL_PROPAGATORS"
若未成功,请保证环境变量的成功设置。
十五、检查探针埋点
若上面问题都检查无误,但依然没有数据上报到 APM 控制台。尝试把埋点信息打印到本地控制台,检查下探针埋点是否正常。
设置环境变量OTEL_TRACES_EXPORTER=console ,重启 PHP 项目,发送请求到该 PHP 服务。
该环境变量会将埋点的信息(如 TraceID、SpanID 等)打印到本地控制台。埋点成功如下:
若未成功,请检查项目中是否导入了需要埋点的库和框架的自动埋点包。
十六、检查 PHP 依赖库和框架
目前自动埋点支持的框架列表详情请参见 OpenTelemetry 产品文档。
如果业务中组件需要 OpenTelemetry 自动埋点,需要在项目中导入对应的自动埋点包。具体操作如下:
若以上问题都已解决,但依然在页面上没有看到数据,或业务中的组件不支持自动接入,请使用 手动接入方案。
十七、手动接入方案
若 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上报接入点,并创建全局TraceProvideuse 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 添加到全局}?>
20、修改应用代码,使用 OpenTelemetry API 创建 Span
1. 在index.php文件中导入所需包。
<?phpuse 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上报接入点,并创建全局TraceProviderinitOpenTelemetry();
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; }});
21、运行应用
1. 执行以下命令。
php -S localhost:8080
2. 在浏览器中访问以下链接。
http://localhost:8080/rolldicehttp://localhost:8080/rolltwodiceshttp://localhost:8080/error
每次访问页面,OpenTelemetry 会创建链路数据,并将链路数据上报至 APM。
22、接入验证
启动 PHP 应用后,通过8080端口访问对应的接口,例如 http://localhost:8080/getID。在有正常流量的情况下,应用性能监控 > 应用列表 中将展示接入的应用,单击应用名称/ID 进入应用详情页。
然后选择实例分析,即可看到接入的应用实例。由于可观测数据的处理存在一定延时,如果接入后在控制台没有查询到应用或实例,请等待30秒左右。