Clockwork – это библиотека и расширение для браузера предоставляющие удобный интерфейс отладки производительности PHP кода.
Расскажу про свой опыт использования и сделаю небольшое сравнение с альтернативами.
Как это работает?
Сначала устанавливаем библиотеку Clockwork с помощью composer в текущий проект: composer require itsgoingd/clockwork
Затем инициализируем где-то в начале жизненного цикла нашего приложения. Есть готовые интеграции для популярных фреймворков: Laravel, Lumen, Slim, Symfony.
Но ничто не мешает использовать эту библиотеку и с любым произвольным PHP кодом. Я, например, подключал к самописному проекту.
В процессе работы нашего PHP кода библиотека Clockwork может собирать метрики. Например, запоминает все SQL вызовы и время их выполнения, накапливает информацию об использованных шаблонах, о текущей сессии и пользователе, о маршруте, максимальное использование памяти (с помощью функции memory_get_peak_usage
), может собирать какие-то отладочные логи.
Если интегрируемся в Laravel приложение, то в комплекте идёт ClockworkServiceProvider
, который подписывается на все основные события Laravel: события работы с базой через Eloquent, события composing для шаблонов, перехватывает работу с кэшем, с отправкой нотификаций, с задачами в очереди и т.п.
Есть также интеграция с Doctrine, Twig, SwiftMailer, Monolog, Guzzle.
Если же нужно подключить Clockwork к какому-то самописному фреймворку, никакой магии нет, придётся самому в нужных точках приложения вызывать методы Clockwork типа «зарегистрируй этот SQL запрос» или «запиши такую-то отладочную информацию в лог» или «только что произошел рендер какого-то шаблона, вот подробности, запиши их» и т.п.
Вся собранная информация накапливается во внутренних массивах библиотеки Clockwork.
В конце жизненного цикла работы приложения нужно вызвать специальный метод библиотеки, который запишет на диск накопленные метрики. По умолчанию запись происходит в json файлы в определённую директорию внутри текущего проекта, настраивается. Также метрики можно хранить и в SQL базе или реализовать свой собственный Storage.
Наконец, перед отправкой ответа на клиент в HTTP заголовки ответа добавляется специальный заголовок X-Clockwork-Id
, содержащий уникальный идентификатор текущего запроса — он указывает на только что записанную на диск метаинформацию.
Видя HTTP заголовок X-Clockwork-Id
, браузерное расширение Clockwork обращается к бэкенду за сохранённой на диск метаинформацией. Чтобы бэкенд смог отдать эту метаинформацию по ID, в нашем приложении должен быть зарегистрировать специальный роут обрабатывающий запросы по адресу __clockwork
. Если мы используем интеграцию с Laravel, то такой роут регистрируется автоматически с помощью ClockworkServiceProvider
. Если же это самописное приложение, то нужно не забыть написать обработку запросов на этот специальный url, что делается достаточно просто.
Также Clockwork умеет собирать клиентские метрики и так называемые Web Vitals, но эти возможности я пока не исследовал.
Безопасность.
Естественно, на production не рекомендуется включать Clockwork по соображениям безопасности. Впрочем, из коробки предоставляются механизмы авторизации, так что доступ к метрикам можно закрыть за паролем или реализовать собственную стратегию проверки прав.
Мой опыт.
На практике я им пользуюсь всего пару дней, выглядит симпатично и удобно, особенно в связке с самописным фреймворком, для которого нет никаких отладочных панелей.
С точки зрения API библиотеки не скажу, что всё идеально. В документации описаны не все публичные методы, нужно читать исходный код библиотеки, очень помогло изучение кода интеграции с Laravel.
Сами исходники несколько запутанные и, к сожалению, пестрят магическими методами __call
, __callStatic
и динамическими вызовами $method(…$args)
, из-за этого при изучении сложно навигироваться по коду в PhpStorm и не работает автокомплит. Тут не помешали бы PhpDoc блоки с описанием всех возможных виртуальных методов.
В процессе нашел баг с фильтрацией входящих запросов по url. В библиотеке есть настройка, с помощью которой можно отключить сбор метрик на определённых адресах, либо наоборот, задать белый список адресов. Я хотел починить этот баг и отправить Pull Request, но обнаружил, что в проекте вообще нет тестов и я не могу подкрепить свой фикс парочкой примеров и регрессионными тестами! Пришлось отправить Pull Request без тестов.
В целом ощущение от культуры кода в этом проекте осталось так себе, однако, библиотека работает, решает свою задачу и я очень доволен находкой!
Альтернативы.
Для измерения похожих метрик выполнения кода на production, в том числе для анализа SQL запросов, я уже давно использую Newrelic. Но в локальной разработке и отладке «здесь и сейчас» Newrelic не подходит (либо я не знаю, как организовать этот процесс).
Для более тонкого изучения производительности конкретной страницы, конкретного скрипта, я обычно использую Blackfire. Но с ним не так удобно, как с Laravel Debugbar или Clockwork: во-первых, при использовании Blackfire рекомендуется отключать Xdebug, потому что при подключённом расширении Xdebug, пусть даже без autostart, все метрики куда-то уплывают и не показывают реальной картины. Во-вторых, с Blackfire не удобно отлаживать ajax запросы. Кстати, про Blackfire у меня был отдельный выпуск Пятиминуки PHP, послушайте: https://5minphp.ru/episode22/
Для локальной профилировки в суровом стиле можно использовать Xdebug profiler и какую-нибудь программу визуализации. Я, например, предпочитаю открывать профили непосредственно в PhpStorm. Но это профилирование только самих PHP функций, нет возможности расставить метки на некоем timeline или собрать лог SQL запросов. И визуализация так себе. Если есть возможность использовать Blackfire, я предпочитаю Blackfire, а не Xdebug profiler. Кстати, браузерное расширение Clockwork умеет визуализировать данные собранные с помощью Xdebug profiler, но я пока не пробовал.
Наконец, к популярным фреймворкам уже есть готовые Debugbars, хорошо интегрированные в инфраструктуру конкретного фреймворка. По умолчанию это похоже на идеальный вариант. Но эти панели рисуются с помощью JavaScript поверх текущей страницы и могут накосячить с вёрсткой или как-то иначе конфликтовать с фронтендом. В моём же случае, когда надо было подключиться к самописному фреймворку, Clockwork оказался весьма удачным выбором!