入门
OpenTelemetry for PHP 可用于生成和导出 跟踪、指标和 日志。
本页将向您展示如何开始使用 OpenTelemetry in PHP。我们将创建一个简单的“掷骰子”应用程序,然后应用零代码和代码插桩来生成 跟踪并将其导出到控制台。然后,我们将发出一些 日志,这些日志也将发送到控制台。
先决条件
OpenTelemetry 需要 PHP 8.0+ 才能进行零代码插桩,但手动插桩适用于 PHP 7.4。
确保已安装以下项
在开始之前,请确保在 shell 中都可用
php -v
composer -v
示例应用程序
以下示例使用基本的 Slim Framework 应用程序。如果您不使用 Slim,那也没关系 — 您可以与其他 Web 框架(如 WordPress、Symfony 和 Laravel)一起使用 OpenTelemetry PHP。有关支持框架的库的完整列表,请参阅 注册表。
依赖项
在一个空目录中初始化一个最小的 composer.json 文件
composer init \
--no-interaction \
--require slim/slim:"^4" \
--require slim/psr7:"^1"
composer update
创建并启动 HTTP 服务器
在同一目录下,创建一个名为 index.php 的文件,内容如下
<?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('/rolldice', function (Request $request, Response $response) {
$result = random_int(1,6);
$response->getBody()->write(strval($result));
return $response;
});
$app->run();
使用 PHP 内置 Web 服务器运行应用程序
php -S localhost:8080
在 Web 浏览器中打开 https://:8080/rolldice 以确保其正常工作。
添加零代码插桩
接下来,您将使用 OpenTelemetry PHP 扩展 自动插桩该应用程序。
由于该扩展是从源代码构建的,因此您需要安装一些构建工具
sudo apt-get install gcc make autoconfbrew install gcc make autoconf使用
PECL构建扩展pecl install opentelemetry注意在 零代码插桩 中详细介绍了安装扩展的替代方法。
将扩展添加到您的
php.ini文件中[opentelemetry] extension=opentelemetry.so验证扩展是否已安装并启用
php --ri opentelemetry向您的应用程序添加其他依赖项,这些依赖项是代码自动插桩所必需的
composer config allow-plugins.php-http/discovery false composer require \ open-telemetry/sdk \ open-telemetry/opentelemetry-auto-slim
设置好 OpenTelemetry PHP 扩展并安装了插桩库后,您现在可以运行您的应用程序并生成一些跟踪了
env OTEL_PHP_AUTOLOAD_ENABLED=true \
OTEL_TRACES_EXPORTER=console \
OTEL_METRICS_EXPORTER=none \
OTEL_LOGS_EXPORTER=none \
php -S localhost:8080
在 Web 浏览器中打开 https://:8080/rolldice 并重新加载页面几次。一段时间后,您应该会在控制台看到 span 打印出来
查看示例输出
[
{
"name": "GET /rolldice",
"context": {
"trace_id": "16d7c6da7c021c574205736527816eb7",
"span_id": "268e52331de62e33",
"trace_state": ""
},
"resource": {
"service.name": "__root__",
"service.version": "1.0.0+no-version-set",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.language": "php",
"telemetry.sdk.version": "1.0.0beta10",
"telemetry.auto.version": "1.0.0beta5",
"process.runtime.name": "cli-server",
"process.runtime.version": "8.2.6",
"process.pid": 24435,
"process.executable.path": "/bin/php",
"process.owner": "php",
"os.type": "darwin",
"os.description": "22.4.0",
"os.name": "Darwin",
"os.version": "Darwin Kernel Version 22.4.0: Mon Mar 6 20:59:28 PST 2023; root:xnu-8796.101.5~3/RELEASE_ARM64_T6000",
"host.name": "OPENTELEMETRY-PHP",
"host.arch": "arm64"
},
"parent_span_id": "",
"kind": "KIND_SERVER",
"start": 1684749478068582482,
"end": 1684749478072715774,
"attributes": {
"code.function": "handle",
"code.namespace": "Slim\\App",
"code.filepath": "/vendor/slim/slim/Slim/App.php",
"code.lineno": 197,
"http.url": "https://:8080/rolldice",
"http.method": "GET",
"http.request_content_length": "",
"http.scheme": "http",
"http.status_code": 200,
"http.flavor": "1.1",
"http.response_content_length": ""
},
"status": {
"code": "Unset",
"description": ""
},
"events": [],
"links": []
}
]
添加手动插桩
追踪
手动跟踪需要一个 TracerProvider。有多种方法可以设置它。在此示例中,我们将使用自动加载的 TracerProvider,它是全局可用的。
将 index.php 替换为以下代码
<?php
use OpenTelemetry\API\Globals;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/vendor/autoload.php';
$tracer = Globals::tracerProvider()->getTracer('demo');
$app = AppFactory::create();
$app->get('/rolldice', function (Request $request, Response $response) use ($tracer) {
$span = $tracer
->spanBuilder('manual-span')
->startSpan();
$result = random_int(1,6);
$response->getBody()->write(strval($result));
$span
->addEvent('rolled dice', ['result' => $result])
->end();
return $response;
});
$app->run();
再次启动内置 Web 服务器,并访问 https://:8080/rolldice。您应该会看到类似的输出,但增加了一个名为 manual-span 的新 span。
请注意,手动 span 的 parent_span_id 包含的值与“{closure}” span 的 context.span_id 相同。手动和自动插桩配合良好,因为它们底层使用相同的 API。
日志记录
现在让我们添加一些日志记录。我们将使用流行的 monolog 日志库来完成此操作,通过一个将日志以 OpenTelemetry 格式发出的处理程序。
首先,让我们安装一些其他依赖项
composer require \
monolog/monolog \
open-telemetry/opentelemetry-logger-monolog
用以下代码替换 index.php 文件
<?php
use Monolog\Logger;
use OpenTelemetry\API\Globals;
use OpenTelemetry\Contrib\Logs\Monolog\Handler;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Log\LogLevel;
use Slim\Factory\AppFactory;
require __DIR__ . '/vendor/autoload.php';
$loggerProvider = Globals::loggerProvider();
$handler = new Handler(
$loggerProvider,
LogLevel::INFO
);
$monolog = new Logger('otel-php-monolog', [$handler]);
$app = AppFactory::create();
$app->get('/rolldice', function (Request $request, Response $response) use ($monolog) {
$result = random_int(1,6);
$response->getBody()->write(strval($result));
$monolog->info('dice rolled', ['result' => $result]);
return $response;
});
$app->run();
使用以下命令启动内置 Web 服务器(注意 OTEL_LOGS_EXPORTER 的更改)
env OTEL_PHP_AUTOLOAD_ENABLED=true \
OTEL_TRACES_EXPORTER=console \
OTEL_METRICS_EXPORTER=none \
OTEL_LOGS_EXPORTER=console \
php -S localhost:8080
这次,当访问 https://:8080/rolldice 时,您应该会像以前一样看到自动插桩跟踪,以及一个从 monolog 处理程序生成的日志记录。
请注意,trace_id 和 span_id 已添加到日志输出中,并且这些值对应于生成日志消息时的活动 span。
查看示例输出
[
{
"name": "{closure}",
"context": {
"trace_id": "8b046fc5d43864058b6a5a18e0dfce3f",
"span_id": "9cf24c78c6868bfe",
"trace_state": ""
},
"resource": {
"service.name": "__root__",
"service.version": "1.0.0+no-version-set",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.language": "php",
"telemetry.sdk.version": "1.0.0beta11",
"telemetry.auto.version": "1.0.0beta6",
"process.runtime.name": "cli-server",
"process.runtime.version": "8.0.27",
"process.pid": 2672,
"process.executable.path": "\/usr\/local\/bin\/php",
"process.owner": "root",
"os.type": "linux",
"os.description": "5.15.0-75-generic",
"os.name": "Linux",
"os.version": "#82-Ubuntu SMP Tue Jun 6 23:10:23 UTC 2023",
"host.name": "f2c0afe83ea9",
"host.arch": "x86_64"
},
"parent_span_id": "df2199a615085705",
"kind": "KIND_INTERNAL",
"start": 1687323704059486500,
"end": 1687323704060820769,
"attributes": {
"code.function": "__invoke",
"code.namespace": "Slim\\Handlers\\Strategies\\RequestResponse",
"code.filepath": "\/usr\/src\/myapp\/vendor\/slim\/slim\/Slim\/Handlers\/Strategies\/RequestResponse.php",
"code.lineno": 28
},
"status": {
"code": "Unset",
"description": ""
},
"events": [],
"links": []
}
]
[
{
"name": "GET \/rolldice",
"context": {
"trace_id": "8b046fc5d43864058b6a5a18e0dfce3f",
"span_id": "df2199a615085705",
"trace_state": ""
},
"resource": {
"service.name": "__root__",
"service.version": "1.0.0+no-version-set",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.language": "php",
"telemetry.sdk.version": "1.0.0beta11",
"telemetry.auto.version": "1.0.0beta6",
"process.runtime.name": "cli-server",
"process.runtime.version": "8.0.27",
"process.pid": 2672,
"process.executable.path": "\/usr\/local\/bin\/php",
"process.owner": "root",
"os.type": "linux",
"os.description": "5.15.0-75-generic",
"os.name": "Linux",
"os.version": "#82-Ubuntu SMP Tue Jun 6 23:10:23 UTC 2023",
"host.name": "f2c0afe83ea9",
"host.arch": "x86_64"
},
"parent_span_id": "",
"kind": "KIND_SERVER",
"start": 1687323704058191192,
"end": 1687323704060981779,
"attributes": {
"code.function": "handle",
"code.namespace": "Slim\\App",
"code.filepath": "\/usr\/src\/myapp\/vendor\/slim\/slim\/Slim\/App.php",
"code.lineno": 197,
"http.url": "https://:8080\/rolldice",
"http.method": "GET",
"http.request_content_length": "",
"http.scheme": "http",
"http.status_code": 200,
"http.flavor": "1.1",
"http.response_content_length": ""
},
"status": {
"code": "Unset",
"description": ""
},
"events": [],
"links": []
}
]
{
"resource": {
"attributes": {
"service.name": "__root__",
"service.version": "1.0.0+no-version-set",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.language": "php",
"telemetry.sdk.version": "1.0.0beta11",
"telemetry.auto.version": "1.0.0beta6",
"process.runtime.name": "cli-server",
"process.runtime.version": "8.0.27",
"process.pid": 2672,
"process.executable.path": "\/usr\/local\/bin\/php",
"process.owner": "root",
"os.type": "linux",
"os.description": "5.15.0-75-generic",
"os.name": "Linux",
"os.version": "#82-Ubuntu SMP Tue Jun 6 23:10:23 UTC 2023",
"host.name": "f2c0afe83ea9",
"host.arch": "x86_64"
},
"dropped_attributes_count": 0
},
"scope": {
"name": "monolog",
"version": null,
"attributes": [],
"dropped_attributes_count": 0,
"schema_url": null,
"logs": [
{
"timestamp": 1687323704059648000,
"observed_timestamp": 1687323704060784128,
"severity_number": 9,
"severity_text": "INFO",
"body": "dice rolled",
"trace_id": "8b046fc5d43864058b6a5a18e0dfce3f",
"span_id": "9cf24c78c6868bfe",
"trace_flags": 1,
"attributes": {
"channel": "otel-php-monolog",
"context": {
"result": 4
}
},
"dropped_attributes_count": 0
}
]
}
}
下一步?
更多信息
- 使用另一个 导出器 来运行此示例,以获取遥测数据。
- 尝试在您自己的应用程序上使用 零代码插桩。
- 了解有关 手动插桩 的更多信息,并尝试一些 示例。
- 查看 OpenTelemetry Demo,其中包含基于 PHP 的 Quote Service。