cyrtolat / spiral-runtime-diagnostics
Runtime diagnostics for Spiral Framework: call logging without redeploying or restarting RoadRunner.
Installs: 2
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/cyrtolat/spiral-runtime-diagnostics
Requires
- php: ^8.1
- psr/container: ^2.0
- psr/log: ^3.0
- spiral/boot: ^3.15
- spiral/config: ^3.15
- spiral/console: ^3.15
- spiral/core: ^3.15
- spiral/files: ^3.15
- spiral/interceptors: ^3.15
- spiral/logger: ^3.15
- symfony/console: ^6.4 || ^7.0 || ^8.0
Requires (Dev)
- nyholm/psr7: ^1.8
- phpunit/phpunit: ^10.5
README
Описание
Библиотека runtime-диагностики для Spiral Framework: временно запускает логирование вызовов в рантайме, без деплоя и без перезапуска RoadRunner-воркеров.
Ключевая идея
Пакет даёт interceptor, совместимый с механизмом interception в Spiral: его можно встроить в ваш pipeline (который вы настраиваете сами в приложении), чтобы получать «первый срез» по последующим вызовам. Включив диагностику на живой системе, вы без деплоя и без перезапуска RoadRunner быстро соберёте поверхностные сигналы (что именно и как долго выполнялось, где чаще падает, где всплески по времени/памяти) и локализуете проблемные кейсы. На этом роль пакета заканчивается: он помогает найти направление, а детальную причину уже нужно разбирать внутри конкретного кода/обработчиков.
Как это работает
Управление диагностикой выполняется через консольные команды. Они не «общаются» с воркерами напрямую, а создают и удаляют специальный временный файл — runfile. В этом файле хранится состояние запущенной диагностики и её параметры (например, включено ли логирование и как долго оно должно работать). Поскольку runfile лежит на сервере в общей для приложения файловой системе, его видят все RoadRunner-воркеры: переключение режима применяется сразу ко всем процессам, а не к одному конкретному воркеру.
Установка и конфигурация
Пакет устанавливается через Composer:
composer require cyrtolat/spiral-runtime-diagnostics
Конфигурация
Пакет использует секцию конфигурации diagnostics. Рекомендуемый способ настройки — опубликовать файл конфигурации в приложение и отредактировать его под своё окружение:
php app.php diag:publish --write
Полезные флаги:
--path=...(по умолчанию@config/diagnostics.php)--force/--overwrite— перезаписать существующий файл
Если конфиг не опубликован, пакет всё равно будет работать: bootloader подставит значения по умолчанию из stubs/diagnostics.php.
Команда
php app.php diag:configвыводит актуальные (эффективные) значения конфигурацииdiagnostics— с учётом опубликованного файла и переменных окружения.
Пример config/diagnostics.php:
return [ // TTL по умолчанию для запуска диагностики (например: 30s, 5m, 1h, 2d, forever) 'duration' => env('DIAGNOSTICS_DURATION', '1h'), // Путь к runfile (должен быть общим для CLI и воркеров: одна ФС/volume) // Рекомендуется делать путь уникальным для приложения/окружения. 'runfile_path' => sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'diagnostics.json', // Канал логирования. Транспорт/handler настраивается в хост-приложении. 'log_channel' => env('DIAGNOSTICS_LOG_CHANNEL', 'diagnostics'), // Ключ атрибута, по которому в контексте вызова хранится исходный callable. 'callable_attribute' => 'callable', ];
Переменные окружения (если используешь stub как есть):
DIAGNOSTICS_DURATION— значение по умолчанию дляdiagnostics.durationDIAGNOSTICS_LOG_CHANNEL— значение по умолчанию дляdiagnostics.log_channel
Параметр
runfile_path— это общий «переключатель» для всех воркеров, поэтому путь должен быть уникальным для приложения/окружения и доступным одновременно и CLI, и воркерам (общая файловая система/volume).
Подключение к Spiral
Для работы пакета требуется три шага интеграции: подключение bootloader (регистрация команд и DI-зависимостей), добавление interceptor в pipeline приложения (желательно первым), и настройка канала логирования, куда будут попадать диагностические события.
1) Подключение Bootloader
Точка входа пакета в Spiral-приложение - это класс Cyrtolat\SpiralRuntimeDiagnostics\DiagnosticsBootloader::class. Его следует указать в Kernel (в список bootloaders): после этого появляются консольные команды php app.php diag:* и регистрируются DI-зависимости, необходимые для корректной работы пакета.
Важно:
DiagnosticsBootloaderне “включает” диагностику и не встраивает interceptor в pipeline. Он только регистрирует команды и биндинги.
2) Подключение Interceptor
Основное звено пакета — Cyrtolat\SpiralRuntimeDiagnostics\DiagnosticsInterceptor::class. Его необходимо добавить в общий pipeline interceptor-ов вашего приложения — где именно это настраивается, зависит от структуры проекта
Важно:
DiagnosticsInterceptorдолжен применяться глобально, чтобы диагностика работала для всех перехватываемых вызовов.
Рекомендуемое размещение — первым в цепочке: так interceptor видит вызовы максимально “снаружи” и не теряет контекст из-за ранних выходов или обработки другими interceptor-ами.
3) Канал логирования
Пакет пишет диагностические события в лог через Psr\Log\LoggerInterface и использует канал из diagnostics.log_channel. При этом он не настраивает «куда именно» писать логи (handlers/transport/ротацию): это зона ответственности хост-приложения.
На практике это означает, что для выбранного канала в приложении должна быть настроена доставка логов в нужное место (отдельный файл, stdout, централизованный сборщик и т.п.). Иначе диагностика формально будет работать, но записи могут смешаться с общими логами, быть отфильтрованы уровнем или вообще не попасть никуда.
Использование
Диагностика управляется консольными командами diag:*: они включают режим на заданное время, показывают статус и позволяют остановить его вручную. Команды не требуют деплоя и не зависят от перезапуска воркеров — режим применяется ко всем процессам через общий runfile.
Команды
php app.php diag:config— текущие (эффективные) значения конфигурацииphp app.php diag:info— краткая справка по режиму и применениюphp app.php diag:publish— публикация шаблона конфигурацииphp app.php diag:start— запуск диагностикиphp app.php diag:status— текущий статус режима по runfilephp app.php diag:stop— остановка режима (удаление runfile, идемпотентно)
Команда
diag:startпринимает необязательный параметр--duration. Значение задаётся в человекочитаемом формате TTL, например30s,5m,1h,2dилиforever. Если параметр не указан, используется значение по-умолчанию.
Формат лог-события
Пакет пишет одну запись на перехваченный вызов.
Message: diagnostics.action
Context (payload):
action(string) — идентификатор действия/вызова, который логируетсяduration_ms(int) — длительность выполнения в миллисекундахok(bool) — признак успеха выполнения (true— успешно,false— ошибка/исключение)memory_usage_bytes(int) — потребление памяти на момент завершения (в байтах)memory_peak_bytes(int) — пиковое потребление памяти за время выполнения (в байтах)memory_usage(string) —memory_usage_bytesв человекочитаемом видеmemory_peak(string) —memory_peak_bytesв человекочитаемом виде
Важно: пакет не настраивает транспорт логов (handlers/файлы/ротацию) и не решает, куда именно попадёт запись. Он лишь пишет событие в канал diagnostics.log_channel; настройка вывода — ответственность хост-приложения.
Практические заметки
- Режим предназначен для кратковременного включения: объём логов может быть большим.
- При использовании forever диагностика не завершится сама — её нужно остановить вручную командой diag:stop.
- По истечении TTL логирование прекращается автоматически, даже если runfile остался на диске.
- Доступ к запуску diag:* команд должен быть ограничен доверенными пользователями/ролями.