PHP-сервери з тривалим часом роботи
PHP-фреймворки, такі як Laravel Octane (з Swoole або RoadRunner), запускають PHP як довготривалий серверний процес замість створення нового процесу на запит. Це змінює поведінку distro в кількох важливих аспектах і вимагає специфічних налаштувань.
Як працюють традиційні PHP-сервери
З PHP-FPM або Apache mod_php кожен HTTP-запит відповідає власному життєвому циклу PHP-процесу:
- PHP-процес стартує → distro bootstrap (OTel SDK ініціалізовано, автоінструментаційні hook-и зареєстровані)
- Запит обробляється → створюються відрізки для HTTP-транзакції та будь-яких інструментованих викликів (curl, PDO, тощо)
- Відповідь відправлена → запускаються PHP shutdown-функції → відрізки очищаються та експортуються
- PHP-процес завершується
Відрізок транзакції distro (OTEL_PHP_TRANSACTION_SPAN_ENABLED) обгортає саме один HTTP-запит: він стартує, коли запит надходить (web SAPI, $_SERVER заповнено) і закінчується, коли процес виходить. Це кореневий відрізок, від якого висять всі дочірні відрізки (curl, DB запити, тощо).
Чим відрізняються сервери, що працюють безперервно
З Laravel Octane (Swoole або RoadRunner) один PHP worker-процес обробляє багато HTTP-запитів поспіль без виходу між ними:
- PHP-процес стартує — worker-процеси стартують з повністю ініціалізованим distro (SDK, hook-и, експортер)
- Кожен HTTP-запит диспетчеризується до worker-а — hook-и worker-а спрацьовують і створюються відрізки
- Відповідь відправлена — PHP shutdown-функції НЕ запускаються (процес продовжує працювати)
- Worker-процес виходить лише при зупинці сервера (graceful stop)
Оскільки worker-процес є CLI-процесом (запущеним через php artisan octane:start), SAPI завжди cli, а не fpm-fcgi або apache2handler. Distro використовує це для розрізнення:
OTEL_PHP_TRANSACTION_SPAN_ENABLED— кореневий відрізок для web SAPI (FPM/Apache). Не актуально тут.OTEL_PHP_TRANSACTION_SPAN_ENABLED_CLI— кореневий відрізок для CLI-процесів. У сервері, що працює безперервно, це обгортає весь час життя сервера (відoctane:startдоoctane:stop), а не окремий запит.
| Аспект | PHP-FPM / Apache | Сервер, що працює безперервно (Octane) |
|---|---|---|
| SAPI | fpm-fcgi / apache2handler | cli |
| Життєвий цикл процесу | Один процес на запит | Один worker обробляє багато запитів |
| PHP shutdown-функції | Запускаються після кожного запиту | Запускаються лише при виході worker-а |
| Distro bootstrap | Запускається на кожному запиті | Запускається один раз на worker при старті |
Відрізок транзакції (_CLI) | Не застосовується | Обгортав би увесь час життя сервера — вимкніть його |
Рекомендована конфігурація
Вимкніть CLI відрізок транзакції
Автоматичний кореневий відрізок (OTEL_PHP_TRANSACTION_SPAN_ENABLED_CLI) охоплює весь процес PHP. На сервері, що працює тривалий час, це означає, що один відрізок триватиме аж до вимкнення сервера,
що не є корисною телеметрією.
export OTEL_PHP_TRANSACTION_SPAN_ENABLED_CLI=false
OTEL_PHP_TRANSACTION_SPAN_ENABLED_CLI є CLI-специфічним і не має ефекту на web SAPI (FPM/Apache) розгортання.
Вимкніть виведені відрізки
Виведені відрізки (вибірка трасування стека) призначені для традиційного PHP, що працює на основі запитів. На сервері з тривалим часом роботи вибірка виконується безперервно між запитами, що створює шум і споживає ресурси CPU.
export OTEL_PHP_INFERRED_SPANS_ENABLED=false
Це стандартне значення, тому потрібно лише якщо ви раніше увімкнули виведені відрізки глобально.
Процесор відрізків та експорт затримки
Зазвичай distro використовує BatchSpanProcessor, який накопичує відрізки в памʼяті і експортує їх за таймером (стандартно: кожні 5 секунд). PHP є однопотоковим, тому перевірка таймера запускається лише коли новий відрізок завершується через onEnd() — немає фонового tick. Завжди використовуйте graceful stop (php artisan octane:stop, SIGTERM), щоб worker-и могли завершити поточний запит, запустити PHP shutdown-функції і очистити експортер перед виходом. Жорстка зупинка (SIGKILL) обходить все це.
З graceful stop, відрізки, забуферовані в памʼяті, очищуються перед виходом процесу — за умови, що точка доступу OTLP доступна. Однак BatchSpanProcessor вводить затримку експорту, пропорційну частоті надходження запитів. В застосунку з низьким трафіком відрізок, створений о 10:00, може не зʼявитися в колекторі до 10:05 (наступний запит нарешті запустить перевірку таймера). Щоб отримати інформацію майже в режимі реального часу, скористайтеся SimpleSpanProcessor:
export OTEL_PHP_TRACES_PROCESSOR=simple
Кожен відрізок миттєво потрапляє в чергу експорту при onEnd(), незалежно від обсягу трафіку.
Вбудований транспорт C++ цього дистрибутиву (HttpTransportAsync) має власну внутрішню чергу та постійне з’єднання з точкою доступу OTLP, тому перехід на simple не означає один HTTP-запит на кожен відрізок. Рівень PHP синхронно передає дані до черги C++ (швидка операція в середині процесу), а рівень C++ обʼєднує їх у пакети та незалежно надсилає через постійне з’єднання.
Повний приклад
Та сама конфігурація застосовується як до Swoole, так і до RoadRunner:
export OTEL_SERVICE_NAME="my-laravel-octane-app"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
# Налаштування для постійно працюючого сервера
export OTEL_PHP_TRANSACTION_SPAN_ENABLED_CLI=false
export OTEL_PHP_INFERRED_SPANS_ENABLED=false
export OTEL_PHP_TRACES_PROCESSOR=simple
# Swoole
php artisan octane:start --server=swoole
# RoadRunner
php artisan octane:start --server=roadrunner
Як інструментування працює для кожного типу сервера
Swoole
Swoole створює робочі процеси шляхом розгалуження головного процесу PHP. Дистрибутив завантажується один раз у головному процесі, а робочі процеси успадковують його стан ініціалізації (хуки, SDK, з’єднання з експортером). Кожен HTTP-запит у робочому процесі запускає зареєстровані хуки автоматичної інструментації (Laravel, curl, PDO тощо), а відрізки створюються в рамках TracerProvider робочого процесу.
RoadRunner
RoadRunner — це сервер застосунків на базі Go, який керує робочими процесами PHP. На відміну від Swoole, він не використовує відгалуження — кожен робочий процес PHP запускається як окремий процес. Як наслідок, кожен робочий процес самостійно завантажує дистрибутив під час запуску. З точки зору інструментування поведінка є ідентичною: SAPI робочого процесу — cli, він обробляє багато запитів, не завершуючи роботу між ними, і застосовується та сама конфігурація.
Затримка у розкладі BatchSpanProcessor
Якщо ви хочете зберегти BatchSpanProcessor але зменшити затримку експорту, зробіть меншою затримку у розкладі:
export OTEL_BSP_SCHEDULE_DELAY=500 # ms, типово 5000
Це допомагає лише в застосунках зі стабільним трафіком — таймер спрацьовує на onEnd(), так що тихіший застосунок все ще відчуває затримку, пропорційну проміжку між запитами.
Зворотний зв’язок
Чи була ця сторінка корисною?
Дякуємо. Ми цінуємо ваші відгуки!
Будь ласка, дайте нам знати як ми можемо покращити цю сторінку. Ми цінуємо ваші відгуки!