OpenTelemetry: настройка, сбор трейсов и профилирование на примере Drupal

Ваш веб-сайт или веб-сервис работает медленно и не понятно где задержки? Возникают трудно воспроизводимые ошибки? Быстро находить узкие и проблемные места, ускорить работу поможет внедрение OpenTelemetry. OpenTelemetry представляет собой современный открытый стандарт телеметрии для эффективной отладки и профилировки веб-приложений. В этой статье DevOps-инженеры Инитлаб делятся опытом внедрения OpenTelemetry на примере Drupal-проекта — установка и настройка модуля drupal/opentelemetry, настройка экспорта трейсов в OTLP-совместимый бэкенд (Grafana Tempo, Jaeger) и опционально автоинструментирование через PHP-расширение и ветку из issue #3347778. Рассмотрены быстрый старт с DDEV/Grafana, ручные спаны в коде и атрибуты WithSpan. Для Drupal внедрение достаточно просто так как есть готовый модуль. Для других CMS, например Битрикс, а также для приложений на практически любых стеках разработки внедрение более трудоемко, но возможно с использованием открытых SDK OpenTelemetry. В начале — зачем вообще нужна телеметрия, какие метрики дают трейсы и для чего полезна профилировка приложения?


Зачем телеметрия, какие метрики и зачем профилировка

Какие проблемы решает телеметрия

  • «Где тормозит?» — без трейсов видно только общее время ответа (например, 2.3 с). Непонятно, ушло ли время на БД, внешние API, рендеринг или кэш. Трейсы показывают цепочку операций (спаны) и длительность каждой, поэтому узкое место находится быстро.
  • Распределённые запросы — когда один запрос пользователя тянет за собой несколько сервисов (Drupal → API → очередь → воркер), один trace id связывает все спаны в один граф. Видно полный путь запроса и задержки между системами.
  • Редкие сбои — ошибки «то бывает, то нет» проще воспроизвести, когда есть привязка к конкретному trace: по trace id можно посмотреть все операции до падения (какой запрос, какой ответ API, какая страница).
  • Единый стандарт — OpenTelemetry даёт один формат (OTLP) и одну точку инструментирования для логов, метрик и трейсов. Меньше разрозненных решений и проще стыковать Drupal с остальным стеком мониторинга.

Какие метрики можно просматривать (на основе трейсов)

На базе собранных трейсов в Grafana Tempo / Jaeger (и при необходимости в метриках, агрегированных из трейсов) можно смотреть:

Что смотретьЗачем
Длительность запроса (trace)Общее время ответа страницы или API, перцентили (p50, p95, p99) для SLA.
Длительность спановВремя на bootstrap ядра, SQL, кэш, рендеринг, внешние HTTP-вызовы — что именно тянет вниз.
Количество и список спанов на запросПонимание «глубины» запроса: сколько запросов к БД, сколько вызовов кэша, сколько внешних сервисов.
Ошибки по трейсамСпаны со статусом error, исключения (recordException), связь ошибки с конкретным запросом и контекстом.
Зависимости сервисовКакие внешние API/очереди вызываются, как часто и как долго — основа для карты зависимостей и анализа рисков.
Атрибуты спановТекст запроса (например, SQL), URL, имена кэш-бинов, код ответа — для фильтрации и поиска «тяжёлых» операций.

Метрики (счётчики, гистограммы) часто строят поверх трейсов в коллекторе или в Grafana (например, через TraceQL и преобразование в метрики).

Для чего нужна профилировка приложения

Профилировка — это детальный разбор того, как приложение тратит время и ресурсы (CPU, память, I/O) внутри одного запроса или воркера. В контексте OpenTelemetry и трейсов:

  • Трейсы дают «что вызывалось и сколько заняло» на уровне операций (запрос к БД, вызов API, рендер блока). Этого достаточно, чтобы найти медленные участки и лишние вызовы без внедрения в ядро.
  • Профилирование (профилеры по CPU/памяти, flame graphs) даёт «какие функции и строки кода съели время». Его подключают, когда узкое место уже локализовано по трейсам, но нужно понять конкретный код (тяжёлый цикл, неоптимальный алгоритм).

Вместе: телеметрия (трейсы + метрики) отвечает на вопрос «где и в каком сервисе тормозит», профилировка — «какая именно часть кода». Для большинства задач оптимизации Drupal достаточно трейсов (особенно с автоинструментированием PDO, Guzzle, кэша); профилирование добавляют при глубокой оптимизации горячих участков.


О чём эта статья

Полезные ссылки:


Требования

  • Drupal: ^9 || ^10 || ^11
  • PHP: не менее 8.0 (для автоинструментирования — PHP 8+ и расширение opentelemetry)
  • Composer: для установки модуля и зависимостей
  • Бэкенд для трейсов: любой OTLP-совместимый приёмник (Grafana Tempo, OpenTelemetry Collector, Jaeger и т.д.)

Для расширенных возможностей модуля желателен Drupal Core 10.1+ (в нём уже есть изменения из issue #3313355).

Для автоинструментирования (issue #3347778) нужна PHP-расширение opentelemetry-php-instrumentation (ранее расширение называлось otel_instrumentation, сейчас — opentelemetry).


1. Установка модуля OpenTelemetry (официальный релиз)

В корне проекта Drupal:

composer require 'drupal/opentelemetry:^1.0@beta'
drush en opentelemetry -y

Альтернатива без Composer: скачать архив релиза (например, 1.0.0-beta6) и положить в modules/contrib/opentelemetry, затем включить модуль через UI или Drush.

Модуль добавляет страницу настроек: Configuration → Development → OpenTelemetry (/admin/config/development/opentelemetry).

 

Раздел Configuration → Development, пункт OpenTelemetry в Drupal
Рис. 1. Страница конфигурации Drupal: Configuration → Development → OpenTelemetry

 


2. Настройка экспорта трейсов

На странице /admin/config/development/opentelemetry задаётся:

  • Endpoint — URL приёмника трейсов (OTLP). Примеры:
    • Локально с Grafana Stack: http://opentelemetry-grafana:4318 или для Tempo: http://tempo:9411/api/v2/spans
    • OpenTelemetry Collector: http://otel-collector:4318
  • При необходимости — сервисное имя, атрибуты, включение отладочного режима (в т.ч. вывод trace id в ответе для поиска в UI).

После сохранения конфигурации запросы к сайту начнут создавать трейсы и отправлять их на указанный endpoint.

 

Форма настроек OpenTelemetry: Endpoint, протокол, Service Name, Span Plugins
Рис. 2. Форма настроек OpenTelemetry: endpoint, протокол OTLP, Service Name, плагины спанов (Request, Database Statement, Exception)

 


3. Быстрый старт с DDEV и Grafana

Для локальной проверки «из коробки» удобно использовать DDEV и аддон с Grafana/Tempo:

  1. Установить Drupal через DDEV и установить модуль:

    composer require drupal/opentelemetry && drush en opentelemetry
  2. Поднять стек с Grafana/Tempo:

    ddev get MurzNN/ddev-grafana && ddev restart
  3. В настройках модуля (/admin/config/development/opentelemetry) указать endpoint, например: http://opentelemetry-grafana:4318 (или Tempo: http://tempo:9411/api/v2/spans).
  4. Включить при необходимости debug-режим, выполнить запрос к сайту, взять trace id из сообщения.
  5. Открыть Grafana (например, https://<project>.ddev.site:3000/), вкладка Explore → источник Traces (или Tempo) → найти трейс по trace id.

Так вы убедитесь, что трейсы доходят до бэкенда и отображаются в UI.

 

Трейс GET /user/login в Grafana Tempo: таймлайн и иерархия спанов
Рис. 3. Трейс запроса GET /user/login в Grafana Tempo: таймлайн и иерархия спанов (82 спана)

 

Детали спана query-1: SQL-запрос к cache_config, атрибуты и ресурсы
Рис. 4. Детали спана query-1 в Tempo: SQL-запрос к таблице cache_config, атрибуты (db.statement, db.system) и ресурсы (service.name, host.name)

 


4. Ручная инструментация в своём коде

Модуль регистрирует сервис трейсера. Пример использования в кастомном модуле (из документации проекта):

$this->openTelemetryTracer = \Drupal::service('opentelemetry.tracer');
$tracer = $this->openTelemetryTracer->getTracer();
$mainSpan = $tracer->spanBuilder('My custom operation')->startSpan();

// Внешний вызов API
$apiCallSpan = $tracer->spanBuilder("Coindesk API call")->startSpan();
$data = json_decode(
  file_get_contents('https://api.coindesk.com/v1/bpi/currentprice.json')
);
$apiCallSpan->end();

$mainSpan->setAttribute('Bitcoin value', $data->bpi->USD->rate_float);
$mainSpan->addEvent('Starting bots tuning', ['bots available' => 3]);
// ... вложенные спаны и события ...
$mainSpan->end();

Имена спанов, атрибуты и события затем видны в бэкенде трейсов (Tempo, Jaeger и т.д.).


5. Автоинструментирование (issue #3347778)

Идея issue #3347778 — использовать OpenTelemetry PHP auto-instrumentation, чтобы оборачивать типовые операции без внесения кода в ядро Drupal:

  • слой PDO (SQL),
  • Guzzle Client (исходящие HTTP),
  • рендеринг,
  • KeyValue store,
  • кэш-бины,
  • DrupalKernel,

и при необходимости добавлять собственные хуки в кастомных модулях.

5.1. Установка PHP-расширения opentelemetry

Расширение переименовано: раньше — otel_instrumentation, сейчас — opentelemetry (см. PR #49).

Через PECL:

pecl install opentelemetry

В php.ini (или в конфиге пула PHP-FPM) добавляется:

extension=opentelemetry

В Docker (официальные образы PHP):

install-php-extensions opentelemetry-php/ext-opentelemetry@main
# или через PECL/pickle:
install-php-extensions opentelemetry[-beta|-stable|-latest]

Проверка:

php --ri opentelemetry

Если установлено конфликтующее расширение (например, Blackfire), его нужно отключить или настроить opentelemetry.conflicts в php.ini.

5.2. Использование ветки с автоинструментированием (issue fork)

Код с поддержкой автоинструментирования пока в ветке issue fork, а не в стабильном релизе модуля.

Установка из issue fork через Composer (в корне Drupal):

composer config repositories.opentelemetry-3347778 vcs https://git.drupalcode.org/issue/opentelemetry-3347778.git
composer require drupal/opentelemetry:dev-3347778-support-auto-instrumentation
drush en opentelemetry -y

Либо клонировать fork и подключить как path-репозиторий:

git clone https://git.drupalcode.org/issue/opentelemetry-3347778.git modules/contrib/opentelemetry
cd modules/contrib/opentelemetry
git checkout 3347778-support-auto-instrumentation

В composer.json проекта добавить:

"repositories": [
  {
    "type": "path",
    "url": "modules/contrib/opentelemetry"
  }
],
"require": {
  "drupal/opentelemetry": "*"
}

После composer update drupal/opentelemetry и включения модуля при наличии установленного расширения opentelemetry в PHP станут активны хуки автоинструментирования (PDO, Guzzle, кэш, ядро и т.д. — в объёме, реализованном в этой ветке).

Патчи и скриншоты по issue можно посмотреть на странице #3347778 (например, patch с WithSpanHandler).


6. Атрибуты WithSpan и SpanAttribute (расширение)

Если используется расширение opentelemetry-php-instrumentation, в своём коде можно помечать методы атрибутами (включив в php.ini opentelemetry.attr_hooks_enabled = On):

use OpenTelemetry\API\Instrumentation\WithSpan;
use OpenTelemetry\API\Instrumentation\SpanAttribute;

class MyService {
  #[WithSpan('custom_span_name', \OpenTelemetry\API\Trace\SpanKind::KIND_INTERNAL, ['my-attr' => 'value'])]
  public function tracedMethod(
    #[SpanAttribute] string $username,
    #[SpanAttribute('custom_attr_name')] string $foo
  ): void {
    // ...
  }
}

Так можно добавлять трейсинг к выбранным методам без явного вызова spanBuilder() в коде.


7. Рекомендуемая схема развёртывания

  1. Сбор трейсов: Drupal (модуль OpenTelemetry) → OTLP HTTP/gRPC → приёмник (OpenTelemetry Collector или напрямую Tempo/Jaeger).
  2. Просмотр: Grafana (Tempo) или Jaeger UI.
  3. Опционально: PHP-расширение opentelemetry + ветка 3347778-support-auto-instrumentation для автоинструментирования PDO, Guzzle, кэша и ядра.
  4. Кастомная логика: ручные спаны через \Drupal::service('opentelemetry.tracer') или атрибуты WithSpan/SpanAttribute.

8. Краткое содержание

ЗадачаДействие
Базовый трейсинг запросов DrupalУстановить drupal/opentelemetry, настроить endpoint на /admin/config/development/opentelemetry
Локальная проверкаDDEV + MurzNN/ddev-grafana, endpoint на Grafana/Tempo, смотреть трейсы в Explore
Детальные спаны по SQL, HTTP, кэшуУстановить PHP-расширение opentelemetry, использовать ветку из issue fork #3347778
Свой код в трейсахИспользовать opentelemetry.tracer и spanBuilder() или атрибуты WithSpan при включённом расширении

Документация модуля и issue queue: drupal.org/project/opentelemetry, issues. Issue по автоинструментированию: #3347778.

9. Заключение

OpenTelemetry — универсальная открытая технология, упрощающая отладку и профилировку веб-приложений, может быть применена для любых стеков веб-разработки через соответствующие открытые SDK и спецификации. Специалисты Инитлаб имеют опыт развертывания систем мониторинга веб-приложений с использованием OpenTelemetry. Готовы проконсультировать вас по вопросам внедрения и поддержки мониторинга с поддержкой OpenTelemetry.

Добавить комментарий

Filtered HTML

  • Допустимые HTML-теги: <a href hreflang> <em> <strong> <cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <pre> <br> <h1> <h2 id> <h3 id>
  • Строки и абзацы переносятся автоматически.
  • Web page addresses and email addresses turn into links automatically.