Ручное внедрение OpenTelemetry в PHP-приложение

Материал из Документация Ключ-АСТРОМ
Версия от 18:12, 9 октября 2025; IKuznetsov (обсуждение | вклад) (Новая страница: «В этом пошаговом руководстве показано, как добавить возможность наблюдения в ваше '''PHP-п...»)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)

В этом пошаговом руководстве показано, как добавить возможность наблюдения в ваше PHP-приложение с помощью PHP-библиотек и инструментов OpenTelemetry.

Получение данных для доступа к Ключ-АСТРОМ

Определить базовый URL API

Подробную информацию о сборке базового URL-адреса конечной точки OTLP см. в разделе Экспорт с помощью OTLP. URL-адрес должен заканчиваться на /api/v2/otlp.

Получить токен доступа API

Токен доступа для сбора трассировок, логов и метрик можно создать в разделе Токены доступа.

Экспорт с помощью OTLP содержит более подробную информацию о формате и необходимых областях доступа.

Инструментирование своего приложения

1. Используйте Composer для установки следующих двух зависимостей.

composer require php-http/guzzle7-adapter

composer require open-telemetry/opentelemetry

2. Создайте новый файл otel.php и сохраните следующий код.

<?php

declare(strict_types=1);

require __DIR__ . '/vendor/autoload.php';

// ===== OpenTelemetry Imports =====

use Monolog\Handler\StreamHandler;

use Monolog\Logger;

use OpenTelemetry\Contrib\Otlp\OtlpHttpTransportFactory;

use OpenTelemetry\Contrib\Otlp\SpanExporter;

use OpenTelemetry\SDK\Sdk;

use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;

use OpenTelemetry\SDK\Trace\TracerProvider;

use OpenTelemetry\SDK\Resource\ResourceInfoFactory;

use OpenTelemetry\SDK\Resource\ResourceInfo;

use OpenTelemetry\SDK\Common\Attribute\Attributes;

use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator;

use OpenTelemetry\SemConv\ResourceAttributes;

use OpenTelemetry\SDK\Metrics\MeterProvider;

use OpenTelemetry\Contrib\Otlp\MetricExporter;

use OpenTelemetry\SDK\Common\Time\ClockFactory;

use OpenTelemetry\SDK\Metrics\MetricReader\ExportingReader;

use OpenTelemetry\Contrib\Otlp\LogsExporter;

use OpenTelemetry\SDK\Logs\LoggerProvider;

use OpenTelemetry\SDK\Logs\Processor\SimpleLogRecordProcessor;

use OpenTelemetry\Contrib\Logs\Monolog\Handler;

use Psr\Log\LogLevel;

// ===== GENERAL SETUP =====

$DT_API_URL = '';

$DT_API_TOKEN = '';

$dtMetadata = [];

foreach (['/var/lib/astromkey/enrichment/dt_metadata.properties',

              'dt_metadata_e617c525669e072eebe3d0f08212e8f2.properties',

              '/var/lib/astromkey/enrichment/dt_host_metadata.properties'] as $filePath) {

try {

if (file_exists($filePath)) {

$props = str_starts_with($filePath, '/var/') ? parse_ini_file($filePath) : parse_ini_file(trim(file_get_contents($filePath)));

$dtMetadata = array_merge($dtMetadata, $props);

}

} catch (Exception $e) {}

}

$resource = ResourceInfoFactory::defaultResource()->merge(ResourceInfo::create(Attributes::create([$dtMetadata,

        ResourceAttributes::SERVICE_NAME => 'php-quickstart'])));

// ===== TRACING SETUP =====

$transport = (new OtlpHttpTransportFactory())->create($DT_API_URL . '/v1/traces', 'application/x-protobuf', [ 'Authorization' => 'Api-Token ' . $DT_API_TOKEN ]);

$exporter = new SpanExporter($transport);

$tracerProvider =  new TracerProvider(new SimpleSpanProcessor($exporter), null, $resource);

// ===== METRIC SETUP =====

$reader = new ExportingReader(

new MetricExporter((new OtlpHttpTransportFactory())->create($DT_API_URL . '/v1/metrics', 'application/x-protobuf', [ 'Authorization' => 'Api-Token ' . $DT_API_TOKEN ])),

ClockFactory::getDefault()

);

$meterProvider = MeterProvider::builder()->setResource($resource)->addReader($reader)->build();

// ===== LOG SETUP =====

$transport = (new OtlpHttpTransportFactory())->create($DT_API_URL . '/v1/logs', 'application/x-protobuf', [ 'Authorization' => 'Api-Token ' . $DT_API_TOKEN ]);

$exporter = new LogsExporter($transport);

$loggerProvider = LoggerProvider::builder()

->addLogRecordProcessor(new SimpleLogRecordProcessor($exporter))

->setResource($resource)

->build();

$handler = new Handler($loggerProvider, LogLevel::INFO);

$monolog = new Logger('example', [$handler]);

// ===== REGISTRATION =====

Sdk::builder()

->setTracerProvider($tracerProvider)

->setMeterProvider($meterProvider)

->setLoggerProvider($loggerProvider)

->setPropagator(TraceContextPropagator::getInstance())

->setAutoShutdown(true)

->buildAndRegisterGlobal();

Расширение данных Ключ-АСТРОМ

Операции чтения файлов, анализирующие файлы dt_metadata в примере кода, пытаются прочитать файлы данных ЕдиногоАгента, чтобы расширить запрос OTLP и гарантировать, что вся соответствующая информация о топологии доступна в Ключ-АСТРОМ.

3. Настройте переменные $DT_API_URL и $DT_API_TOKEN с otel.php соответствующими значениями.

4. Включите otel.php во все PHP-файлы где необходимо инициализировать OpenTelemetry.

require('otel.php');

Добавление телеметрических сигналов вручную

Создание интервалов

1. Для создания новых интервалов нам сначала нужен объект трассировки.

$tracer = Globals::tracerProvider()->getTracer('my-tracer');

2. Теперь с помощью $tracer, мы можем использовать конструктор интервалов для создания и запуска новых интервалов.

$span = $tracer->spanBuilder('Call to /myendpoint')->startSpan();

try

{

    $span->setAttribute('http.method', 'GET');

    $span->setAttribute('net.protocol.version', '1.1');

    // TODO your code goes here

}

finally

{

    $span->end();

}

В приведенном выше коде мы:

  • Создали новый диапазон и назовите его «Call to /myendpoint».
  • Добавили два атрибута, следуя семантическому соглашению об именовании, специфичные для действия этого диапазона: информацию о методе HTTP и версии.
  • Добавили TODO вместо конечной бизнес-логики
  • Вызвали метод span end(), чтобы закрыть span (в блоке finally, чтобы гарантировать вызов метода)

Собор метрик

1. Как и в случае с трассировками, нам необходимо получить объект-счетчик.

$meterProvider = Globals::meterProvider();

$meter = $meterProvider->getMeter('my-meter');

2. С помощью $meter мы теперь можем создавать отдельные инструменты, например, счетчик.

$requestCounter = $meter->createCounter('request_counter');

3. Теперь мы можем вызвать метод add() для записи новых значений $requestCounter с помощью счетчика и сохранения дополнительных атрибутов (например, action.type).

$requestCounter->add(1, [ 'action.type' => 'create' ]);

4. Синхронные показатели, такие как счетчик, экспортируются при вызове forceFlush() или shutdown() счетчиков.

$meterProvider->forceFlush();

Подключение логов

Поскольку переменная $monolog уже инициализирована и настроена (см. выше), мы можем напрямую подключаться к настроенной конечной точке OpenTelemetry в Ключ-АСТРОМ.

Обеспечение распространения контекста (необязательно)

Распространение контекста особенно важно, когда задействованы сетевые вызовы (например, REST).

Если вы используете автоматическое инструментирование и ваши сетевые библиотеки соответствуют PSR-15 (извлечение для входящих запросов) и PSR-18 (внедрение для исходящих запросов), распространение контекста будет обрабатываться автоматически. В противном случае ваш код должен это учитывать.

Извлечение контекста при получении запроса

В следующем примере мы предполагаем, что получили HTTP-запрос со встроенной контекстной информацией, которую мы собираемся извлечь для продолжения трассировки.

Для этого сначала создаем объект request с ServerRequestCreator::createFromGlobals().

Затем мы получаем объект TraceContextPropagator и передаём наш объект request методу extract(). Это возвращает объект контекста (на основе информации, предоставленной нам через HTTP-вызов), который мы можем впоследствии использовать для продолжения этой трассировки с нашими собственными интервалами.

// Create a request object based on PHP's global arrays (for example, $_SERVER)

$request = ServerRequestCreator::createFromGlobals();

// Obtain propagator instance

$tracePropagator = TraceContextPropagator::getInstance();

// Extract context information from headers and recreate context

$context = $tracePropagator->extract($request->getHeaders());

// Start new span and set received context as parent

$span = $tracer->spanBuilder("my-span")

  ->setParent($context)

  ->setSpanKind(SpanKind::KIND_SERVER)

  ->startSpan();

$scope = $span->activate();

try

{

    // TODO your code here

}

finally

{

    $span->end();

    $scope->detach();

}

Внедрение контекста при отправке запросов

В следующем примере мы используем PHP-библиотеку cURL для отправки HTTP-запроса другому сервису и предоставляем наш существующий контекст как часть HTTP-заголовков нашего запроса.

Для этого мы сначала получаем экземпляр TraceContextPropagator, для которого вызываем метод inject и передаем пустой массив $traceContext. Этот вызов заполняет массив соответствующими данными заголовка ассоциативным образом.

Поскольку для вызова cURL нам нужен простой строковый массив, нам нужно преобразовать его перед передачей в cURL. Для этого $traceContext на следующем шаге мы выполняем цикл и добавляем имена и значения в $contextData.

Теперь мы готовы инициализировать наш экземпляр cURL, передать $contextData и выполнить HTTP-вызов.

$traceContext = []; $contextData = [];

$tracePropagator = TraceContextPropagator::getInstance();

$tracePropagator->inject($traceContext);

// Convert associative array into plain string array

foreach ($traceContext as $name => $value) $contextData[] = "$name: $value";

// Initialize cURL

$ch = curl_init('[URL]');

// Set propagation headers

curl_setopt($ch, CURLOPT_HTTPHEADER, $contextData);

// Execute cURL call

curl_exec($ch);

Настройка сбора данных в соответствии с требованиями конфиденциальности (необязательно)

Хотя Ключ-АСТРОМ автоматически собирает все атрибуты OpenTelemetry, в веб-интерфейсе Ключ-АСТРОМ сохраняются и отображаются только значения атрибутов, указанные в списке разрешенных. Это предотвращает случайное сохранение персональных данных, позволяя вам соблюдать требования к конфиденциальности и контролировать объем хранимых данных мониторинга.

Чтобы просматривать пользовательские атрибуты, необходимо сначала разрешить их использование в веб-интерфейсе Ключ-АСТРОМ.

Проверка загрузки данных в Ключ-АСТРОМ

После завершения инструментирования вашего приложения выполните несколько тестовых действий для создания и отправки демонстрационных трассировок, метрик и логов, а также проверьте, что они были правильно загружены в Ключ-АСТРОМ.

Чтобы сделать это для трассировок, перейдите в раздел Трассировки и выберите вкладку Распределенные трассировки. Если вы используете ЕдиныйАгент, выберите PurePaths .

Для просмотра метрик и логов перейдите в раздел Метрики или Логов или Логи и события.