До основного вмісту

Slowlog PHP-FPM: як знайти повільні скрипти

PHP · 18.10.2026 · 3 хв читання
Ілюстрація до статті «Slowlog PHP-FPM: як знайти повільні скрипти»

Slowlog PHP-FPM показує стек викликів запиту в момент, коли він працює довше заданого порогу, — це знімок одного застряглого місця виконання, а не безперервна трасування. Інструменту для читання цього знімка і відділення повільного коду від повільної бази даних у каталозі раніше не було.

Що саме пише slowlog і чого не пише

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

Знімок не містить історії викликів у часі — лише один зріз на момент таймауту. Розбір того, що і як потрапляє в error_log і у вивід фаталів, окремо описано в статті про логи PHP.

Увімкнення slowlog у конфігурації пулу

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

Порог варто вибирати за очікуваним часом відповіді конкретного ендпоінта: для звичайної сторінки 5 секунд вже підозріло довго, а для фонового важкого звіту той самий порог спрацює на кожному запиті і забʼє лог марними трасуваннями.

Як читати трасування

У записі видно ланцюжок викликів функцій з номерами рядків — зверху найзовнішній виклик, знизу поточна, застрягла функція. Якщо знизу виклик функції роботи з файлами, мережею чи базою даних, найімовірніше скрипт чекає зовнішній ресурс, а не рахує щось процесором.

  • Зовнішній HTTP-запит до API без таймауту чи з великим таймаутом
  • Запит до бази даних без індексу — характерний ланцюжок викликів PDO чи mysqli
  • Цикл з N+1 запитами, де кожна iтерація чекає окрему відповідь від бази
  • Регулярний вираз з катастрофічним 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, який лише приховує симптом.

Чи була стаття корисною?
← Назад до бази знань Поставити питання підтримці