Ответ
Когда баг не воспроизводится в локальном окружении, я действую по следующему алгоритму:
- Воссоздание окружения: Разворачиваю максимально приближенную к production среду, используя Docker-контейнеры с идентичными версиями ПО (PHP, веб-сервер, СУБД) и настройками.
- Сбор данных: Запрашиваю у тестировщика или из системы мониторинга полный контекст:
- Точные шаги воспроизведения.
- Логи ошибок (PHP, nginx/Apache).
- Данные окружения (
phpinfo(),$_SERVER). - Состояние данных на момент ошибки (дампы БД, кэша).
- Детективное расследование: Ищу различия между средами. Частые причины:
- Разные версии PHP или расширений: Проверяю
php -vиphp -m. - Конфигурация: Настройки памяти (
memory_limit), времени выполнения (max_execution_time). - Проблемы с данными: Уникальное состояние базы данных или кэша, специфичное для продакшена.
- Поведение пользователя: Особые куки, сессия, права доступа (ACL).
- Разные версии PHP или расширений: Проверяю
Пример инструментария для отладки:
// Временное логирование в контроллере или middleware для сбора контекста
if ($_SERVER['REMOTE_ADDR'] == 'IP_ТЕСТИРОВЩИКА') {
error_log(json_encode([
'timestamp' => date('c'),
'request_uri' => $_SERVER['REQUEST_URI'],
'request_params' => $_REQUEST,
'session_id' => session_id(),
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'backtrace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5)
], JSON_PRETTY_PRINT));
}
Если проблема остаётся неуловимой, подключаю инструменты распределённой трассировки (например, OpenTelemetry) или мониторинга ошибок (Sentry, Bugsnag), чтобы поймать её при следующем возникновении в проде.
Ответ 18+ 🔞
Ну вот, опять этот цирк начинается. Баг есть, а на локалке его нихуя нет, как будто он испарился. Прямо волшебство какое-то, ёпта. Ладно, действую по накатанной, хоть терпения ноль ебать уже от этих невидимок.
Первым делом — окружение. Надо поднять такую же среду, как на проде, до последней запятой в конфиге. Беру Docker, выкатываю контейнеры с теми же версиями PHP, того же Nginx, базу ту же самую. Не «примерно такую же», а один в один, потому что чёрт, как известно, кроется в деталях, а в нашем случае — в разнице версий расширений.
Дальше — сбор улик. Пишу тестировщику или лезу в логи мониторинга. Мне нужно всё: точные шаги, что он тыкал, что вводил, под каким пользователем. Логи ошибок с прода — это святое. Ещё вытягиваю phpinfo() с того сервака и дамп окружения $_SERVER. А самое главное — состояние данных на момент пиздеца. Потому что часто бывает, что баг вылазит только при какой-то ебанутой комбинации записей в базе или сбитом кэше. Без этого — просто пальцем в небо.
И вот начинается самое интересное — детектив. Сравниваю две среды, ищу, где наебнулось. Частые подозреваемые:
- Версии. На проде PHP 8.2.1, а у меня 8.2.0 — и какая-нибудь херня уже по-другому работает. Проверяю
php -vиphp -mдосконально. - Настройки. На продакшене
memory_limitзажали, илиmax_execution_timeстоит три секунды, а скрипт на пять тянет. - Данные. В базе на проде лежит какая-то манда с ушами, которую десять лет назад засунули, и только сейчас код на неё наткнулся.
- Пользователь. У него особенные куки, просроченная сессия или права доступа, которых больше ни у кого нет.
Если баг хитрожопый и не ловится, втыкаю в код временные ловушки. Где-нибудь в контроллере или middleware, чтобы логировать всё подряд, но только для IP-адреса того, кто баг воспроизводит.
// Временное логирование в контроллере или middleware для сбора контекста
if ($_SERVER['REMOTE_ADDR'] == 'IP_ТЕСТИРОВЩИКА') {
error_log(json_encode([
'timestamp' => date('c'),
'request_uri' => $_SERVER['REQUEST_URI'],
'request_params' => $_REQUEST,
'session_id' => session_id(),
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'backtrace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5)
], JSON_PRETTY_PRINT));
}
Это как камеру скрытого наблюдения поставить. Часто после такого выясняется, что запрос приходит не с теми параметрами, или сессия сломана, или ещё какая хуйня.
Ну а если и это не помогло, и баг ускользает как хитрая жопа, тогда пускаю в ход тяжёлую артиллерию. Настраиваю распределённую трассировку, типа OpenTelemetry, или подключаю Sentry. Пусть ловят эту невидимку при следующем появлении на проде. Рано или поздно она вылезет, и тогда я её возьму за ебальник. Главное — методичность и не опускать руки, даже когда овердохуища уже бесит.