К основному содержимому

Slowlog PHP-FPM: как найти медленные скрипты

PHP · 18.10.2026 · 3 мин чтения
Иллюстрация к статье «Slowlog PHP-FPM: как найти медленные скрипты»

Slowlog PHP-FPM показывает стек вызовов запроса в момент, когда он работает дольше заданного порога, — это снимок одного застрявшего места выполнения, а не непрерывная трассировка. Инструмента для чтения этого снимка и отделения медленного кода от медленной базы данных в каталоге раньше не было.

Что именно пишет slowlog и чего не пишет

Если запрос работает дольше request_slowlog_timeout, PHP-FPM один раз делает дамп трассировки стека — какая функция и строка исполнялись на момент снятия снимка. Это не похоже на обычный error_log: там видно сообщение после завершения скрипта, а slowlog показывает происходящее в реальном времени, пока процесс ещё жив.

Snapshot не содержит истории вызовов во времени — только один срез на момент таймаута. Разбор того, что и как попадает в error_log и в вывод фаталов, отдельно описан в статье про логи PHP.

Включение slowlog в конфигурации пула

Директивы задаются в конфигурации пула, рядом с остальными параметрами PHP-FPM, разобранными в статье про пулы и воркеры PHP-FPM. request_slowlog_timeout определяет порог, после которого снимается трассировка, а slowlog — путь к файлу.

Порог стоит выбирать по ожидаемому времени ответа конкретного эндпоинта: для обычной страницы 5 секунд уже подозрительно долго, а для фонового тяжёлого отчёта тот же порог сработает на каждом запросе и забьёт лог бесполезными трассировками.

Как читать трассировку

В записи видно цепочку вызовов функций с номерами строк — сверху самый внешний вызов, снизу текущая, застрявшая функция. Если внизу вызов функции работы с файлами, сетью или базой данных, скорее всего скрипт ждёт внешний ресурс, а не считает что-то процессором.

  • Внешний HTTP-запрос к API без таймаута или с большим таймаутом
  • Запрос к базе данных без индекса — характерная цепочка вызовов PDO или mysqli
  • Цикл с N+1 запросами, где каждая итерация ждёт отдельный ответ от базы
  • Регулярное выражение с катастрофическим backtracking на длинной строке
  • Ожидание файловой блокировки, которую держит другой процесс

Таблица основных параметров slowlog

Значения в таблице — ориентир для старта, а не универсальный стандарт: порог подбирается по профилю конкретного эндпоинта.

ПараметрЧто делаетТипичный старт
slowlogпуть к файлу трассировок/var/log/php8.3-fpm-slow.log
request_slowlog_timeoutпорог, после которого пишется трассировка5s
request_terminate_timeoutпринудительное завершение зависшего запроса30s
slowlog_timeout_depthглубина стека в записи трассировки128

Slowlog против slow query log MySQL

Если трассировка упирается в вызов PDO или mysqli, это признак медленного запроса к базе, а не медленного PHP-кода. В этом случае точный диагноз даёт slow query log самой базы — включение и разбор описаны в статье про MySQL Slow Query Log, где видно сам SQL и число просканированных строк.

Ротация: slowlog растёт быстро при низком пороге на нагруженном сайте, поэтому файл стоит включить в logrotate так же, как обычные логи Nginx и PHP, иначе он займёт всё свободное место на диске.

slowlog = /var/log/php8.3-fpm-slow.log
request_slowlog_timeout = 5s
request_terminate_timeout = 30s

Частые вопросы

Можно ли держать slowlog включённым постоянно в продакшене?

Да, если порог выбран разумно: запись делается только когда запрос превышает порог, поэтому постоянно включённый slowlog с порогом 5 секунд не нагружает сервер на обычных быстрых запросах.

Почему трассировка пустая или обрывается на первой строке?

Чаще всего это слишком маленькое значение slowlog_timeout_depth: оно ограничивает глубину стека, и если застрявший вызов находится глубже заданного предела, трассировка просто обрывается.

В трассировке видна функция curl_exec, что делать?

Это внешний HTTP-запрос без таймаута или с большим таймаутом — нужно добавить или уменьшить таймаут самого запроса, а не увеличивать request_slowlog_timeout, который только прячет симптом.

Статья помогла?
← Назад в базу знаний Задать вопрос поддержке