Зачем вообще трогать логирование PostgreSQL (и причём тут pgbadger)
Когда начинаются «внезапные» тормоза в базе, чаще всего выясняется простая вещь: логов либо нет, либо они не пригодны для анализа. Для админа/DevOps это превращается в раскопки по косвенным признакам (CPU, iowait, жалобы приложения), вместо прямого ответа: какой запрос, откуда, как долго и как часто.
pgbadger решает задачу «превратить простыню логов PostgreSQL в отчёт»: топ медленных запросов, распределения по времени, источники, пользователи, базы, ошибки. Но качество отчёта зависит от того, что именно вы пишете в лог и насколько стабилен формат.
Ниже — практический пресет для PostgreSQL 10+ (подойдёт и для более новых версий): включаем полезные логи для поиска тормозов и делаем их удобными для pgbadger.
Ключевые параметры логирования: минимальный рабочий набор
Логирование настраивается в postgresql.conf (или через ALTER SYSTEM). Базовый набор параметров, который реально помогает при разборе инцидентов:
logging_collector— сбор логов в файлы;log_directory,log_filename, ротация — чтобы логи не росли бесконечно;log_destination— формат логов (текст или CSV);log_line_prefix— поля в начале строки (важно для текстового формата);log_min_duration_statement— логирование медленных запросов по порогу;log_lock_waits,deadlock_timeout— контекст по ожиданиям блокировок;log_checkpoints,log_autovacuum_min_duration— фоновые события, которые тоже влияют на latency.
pgbadger умеет разбирать и текстовые логи, и CSV. Для стабильного парсинга в проде CSV обычно надёжнее: меньше сюрпризов из‑за формата и переносов строк.
Если база крутится на отдельном сервере, полезно сразу закладывать место под логи и отчёты. На практике удобнее держать PostgreSQL и аналитику рядом на небольшой VDS, чтобы pgbadger не гонял большие файлы по сети и не зависел от рабочей станции.
Текстовые логи: какой log_line_prefix нужен, чтобы pgbadger был полезным
Если вы используете обычные текстовые логи (log_destination = 'stderr' при включённом logging_collector), то log_line_prefix критичен. Он должен давать pgbadger стабильные поля для группировки и помогать вам быстро понимать контекст.
Рекомендуемый log_line_prefix
Практичный префикс, который обычно хорошо «ложится» в отчёты и удобен при чтении глазами:
log_line_prefix = '%m [%p] db=%d,user=%u,app=%a,client=%h '
Что означают токены:
%m— timestamp с миллисекундами;%p— PID backend-процесса (удобно склеивать события одного подключения);%d— база;%u— пользователь;%a—application_name(очень полезно, если задаёте его в драйвере/пуле);%h— хост клиента (или пусто для локальных сокетов).
Именованные ключи (db=, user=, app=) помогают даже при «грязных» значениях. Заканчивайте префикс пробелом — мелочь, но снижает шанс «склейки» с последующим текстом.
Частые ошибки
Слишком короткий префикс вроде %t даёт время, но убивает диагностику: сложно понять, кто генерирует нагрузку и из какого сервиса идёт поток запросов.
Слишком «жирный» префикс (добавили всё подряд) увеличивает размер логов и ухудшает читаемость. Добавляйте только то, чем реально будете пользоваться в разборе.

CSV логирование (csvlog): когда лучше выбрать его
Формат csvlog хорош тем, что структура фиксирована: каждое поле — отдельная колонка. pgbadger умеет разбирать CSV и обычно делает это предсказуемее, чем текстовые логи с экзотическими префиксами.
Минимальная настройка для CSV:
logging_collector = on
log_destination = 'csvlog'
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d.csv'
log_rotation_age = 1d
log_rotation_size = 0
В режиме csvlog значение log_line_prefix не играет роли: CSV содержит свои поля. Это удобно, если у вас несколько команд/сервисов и вы хотите исключить «религиозные войны» вокруг формата строки.
Логирование медленных запросов: log_min_duration_statement без боли
log_min_duration_statement — самый быстрый способ начать разбор slow queries без внедрения APM и сложных трассировок. Параметр задаёт порог в миллисекундах: всё, что дольше, попадёт в лог.
- Для «горячего» продакшена начните с 500–1000 мс.
- Для проблемного периода можно временно снизить до 100–200 мс.
- На стейдже допустимо поставить 0 и логировать всё, но на проде это почти всегда слишком шумно.
Пример стартовой настройки:
log_min_duration_statement = 500
В логах вы получите длительность и текст запроса, а pgbadger агрегирует это в топы и распределения.
Нужно ли включать log_duration
log_duration пишет длительность каждого завершённого запроса, даже быстрого. Обычно это лавина. В большинстве случаев достаточно log_min_duration_statement.
log_duration = off
Что делать с «шумными» запросами (healthcheck, heartbeat)
Если приложение делает однотипный быстрый запрос каждые N секунд, а в период деградации он иногда перепрыгивает порог — отчёты могут засоряться. Типовые варианты:
- поднять порог
log_min_duration_statement; - отдельно анализировать такие запросы по
application_name; - пересмотреть healthcheck (убрать тяжёлые join/функции, не дергать «дорогие» таблицы).
pgbadger: как подготовить логи и не споткнуться о мелочи
pgbadger можно запускать разово (для расследования) или по расписанию (ежедневные отчёты). Чтобы не получить сюрпризы:
- Ротация: один бесконечный файл = медленнее анализ и больше риска упереться в диск.
- Таймзона: удобнее, когда вся инфраструктура живёт в единой TZ и отчёт совпадает с вашим мониторингом.
- Кодировка: держите UTF-8, аккуратнее с «грязными» строками в запросах.
- Переносы строк в запросах (миграции/DDL): CSV обычно переживает это лучше, чем текстовый формат.
Пример запуска pgbadger для текстовых логов
pgbadger /var/lib/postgresql/data/log/postgresql-*.log -o /var/www/pgbadger/report.html
Пример запуска pgbadger для csvlog
pgbadger /var/lib/postgresql/data/log/postgresql-*.csv -f csv -o /var/www/pgbadger/report.html
Путь к логам зависит от дистрибутива и настроек log_directory. На Debian/Ubuntu с пакетной установкой часто логи лежат в /var/log/postgresql/, а при кастомной инсталляции — внутри каталога данных.
Как связать pgbadger-отчёт с реальными проблемами в проде
Отчёт сам по себе — это приборная панель. Чтобы он давал быстрые действия, держите в голове, что именно вы ищете:
- Top slowest queries: один запрос очень долгий — проблема часто в плане, индексе, статистике, блокировках или внешнем I/O.
- Most frequent queries: запросы по 20–50 мс, но тысячами раз в секунду — оптимизация приложения, кэшей, батчинга.
- Errors: ошибки сериализации, таймауты, дедлоки — индикатор конкуренции.
- Connections: если подключений слишком много, проблема часто в пуллинге и лимитах, а не в самих запросах.
Добавьте контекст: блокировки и autovacuum
Медленный запрос не всегда «плохой» сам по себе — он мог ждать блокировку. Поэтому полезно включить:
log_lock_waits = on
deadlock_timeout = 1s
И отдельно — логирование autovacuum, чтобы видеть, не совпадают ли пики latency с тяжёлыми vacuum:
log_autovacuum_min_duration = 2s
Если после этого в отчётах видно, что тормоза коррелируют с autovacuum, переходите к настройке параметров обслуживания и индексов. У меня есть отдельная практическая заметка про это: как тюнить autovacuum и индексы в PostgreSQL.
Быстрый пресет для PostgreSQL 10+: текстовые логи + pgbadger
Если хотите стартовать с текстовым форматом (stderr) и аккуратным префиксом, берите этот «скелет» и дальше крутите под себя:
logging_collector = on
log_destination = 'stderr'
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d.log'
log_rotation_age = 1d
log_rotation_size = 0
log_line_prefix = '%m [%p] db=%d,user=%u,app=%a,client=%h '
log_min_duration_statement = 500
log_duration = off
log_lock_waits = on
deadlock_timeout = 1s
log_checkpoints = on
log_autovacuum_min_duration = 2s
Почему это хороший старт:
- есть ротация и предсказуемые имена файлов;
- есть идентификация источника запросов через
app,user,db,client; - медленные запросы попадают в лог без спама от быстрых;
- видны блокировки/дедлоки и фоновые операции.
Что выбрать: csvlog или log_line_prefix
Оба подхода рабочие. На практике выбор обычно такой:
- csvlog — если нужна максимальная предсказуемость парсинга, планируется централизованный сбор и не хочется зависеть от формата строки.
- stderr + log_line_prefix — если вы часто читаете логи глазами на сервере, активно используете grep и хотите «человекочитаемую» строку.
Если сомневаетесь — начинайте с
csvlog. Когда станет понятно, какие поля важны именно вам, можно дополнительно настроить текстовый формат для оперативной диагностики.

Чек-лист: чтобы анализ slow queries реально заработал
Включён
logging_collectorи настроена ротация логов.Выбран формат: либо
csvlog, либо корректныйlog_line_prefixдля текстовых логов.Задан разумный порог
log_min_duration_statement(обычно старт — 500–1000 мс).Есть контекст по ожиданиям:
log_lock_waits+deadlock_timeout.pgbadger запускается по расписанию или хотя бы разово при инцидентах.
С разработчиками согласовано использование
application_nameв строках подключения.
Если PostgreSQL «под нагрузкой»: на что обратить внимание помимо логов
Логи и pgbadger покажут «симптомы», но для лечения обычно нужно одно из действий:
- индексы и переписывание запросов (часто видно по повторяющимся медленным SELECT);
- проверка блокировок и транзакций (особенно долгих idle in transaction);
- настройка autovacuum и статистики (плохие планы, bloat, внезапные seq scan);
- дисковая подсистема и fsync-поведение (если тормозит в пиках I/O).
Если вы ещё не выстроили базовую инфраструктуру под проекты, лучше начинать с простой и предсказуемой платформы: виртуальный хостинг для небольших сайтов и сервисов, а для выделенной БД и стабильных логов/отчётов — отдельная VDS.
Первый шаг всё равно один: включить адекватное логирование PostgreSQL, чтобы перестать гадать и начать измерять.


