Сайт использует сookies для хранения данных. Продолжая использовать сайт, вы даёте согласие на работу с этими файлами.

ОК
🧱
Данные
Опубликовано:
29.07.2026
Обновлено:
03.08.2026

jsonlog в PostgreSQL: как навести порядок в логах и перейти на структурированный JSON

Илья Новиков

Обычный текстовый лог PostgreSQL - это поток строк, где нужную ошибку приходится выуживать по крупицам. Один запрос, один сбой, а вы уже тонете в каше из PID’ов, меток времени и фрагментов SQL. К счастью, начиная с 15‑й версии PostgreSQL появилась возможность сразу писать логи в структурированном виде - по‑человечески, в формате JSON. Рассказываем, как включить jsonlog, что именно попадает в такой лог и как встроить его в современный мониторинг без сюрпризов.

Зачем переходить на структурированные логи

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

Структурированный JSON-формат решает эти проблемы:

  • Каждое событие - самостоятельный JSON-объект с фиксированными ключами.
  • Инструменты сбора логов понимают JSON «из коробки», без настройки громоздких grok-шаблонов.
  • Вы можете фильтровать по error_severity, dbname, user или state_code мгновенно.
  • Аналитика по времени сессии, количеству ошибок, проблемным запросам строится на порядок быстрее.

Проще говоря, jsonlog превращает лог PostgreSQL из чёрного ящика в прозрачный источник данных для проактивного управления базой.

Что такое jsonlog и с какой версии PostgreSQL он доступен

jsonlog - это встроенный в ядро PostgreSQL формат вывода логов. Он появился в версии PostgreSQL 15 как новый элемент параметра log_destination. Технически это третий файловый формат после привычных stderr и csvlog.

Принцип прост: коллектор логов записывает каждую запись как одну строку JSON, разделённую переводом строки. Никаких внешних расширений или обёрток - всё работает штатными средствами сервера.

Важно: jsonlog не заменяет системный stderr, а дополняет его. Вы можете оставить текстовые логи в неизменном виде и параллельно получать аккуратные JSON-файлы.

Пошаговое включение jsonlog

Настройка выполняется через знакомый postgresql.conf. При этом все привычные параметры ротации и каталогов остаются общими.

Основные параметры (log_destination, logging_collector)

Для активации нужно прописать формат в log_destination и обязательно включить коллектор логов. Без logging_collector = on файлы на диск писаться не будут.

# Основной минимум
log_destination = 'jsonlog'
logging_collector = on

Эти два параметра - фундамент. Если забудете про logging_collector, JSON‑файл просто не появится, а логи могут уйти только в stderr и потеряться при перезапуске.

Настройка каталога и имён файлов

JSON‑логи используют те же параметры, что и обычные текстовые:

log_directory = 'pg_log' # каталог относительно data-директории
log_filename = 'postgresql-%a.json' # шаблон с strftime-масками

Суффикс .json PostgreSQL добавляет автоматически, когда видит jsonlog в log_destination. В примере выше каждый день будет создаваться файл вида postgresql-Mon.json.

Комбинированное логирование (stderr + jsonlog)

Чтобы продолжать получать текстовые логи и одновременно JSON, перечислите оба направления:

log_destination = 'stderr,jsonlog'

С этим значением в log_directory окажутся два набора файлов: обычные .log (или без расширения) и параллельные .json. Такой дуплекс удобен на время перехода: вы сохраняете привычную картину, а JSON‑логи постепенно подключаете к централизованной системе.

Ротация и суффикс .json

Ротация управляется теми же знакомыми механизмами PostgreSQL. Можно задать log_rotation_age и log_rotation_size, или построить имя файла на масках %a, %d, %H - тогда новый файл будет создаваться по расписанию.

Следите, чтобы шаблон в log_filename сам по себе не содержал .json, иначе получите удвоение. Достаточно указать корень, а расширение добавится автоматически.

После изменения параметров достаточно выполнить pg_ctl reload либо SELECT pg_reload_conf(). Перезапуск сервера не требуется.

Анатомия одной JSON‑строки: все ключи и их смысл

Каждая строка JSON‑лога - это плоский объект с примерно двумя десятками ключей. Все они строго типизированы: строки, числа, иногда null для отсутствующих данных.

Вот основной костяк полей и их практическое применение:

Ключ Тип Что значит
timestamp string Время события с миллисекундами, идеально для сортировки
user string Пользователь, под которым установлено соединение
dbname string База данных сессии
pid number ID серверного процесса, помогает связать с pg_stat_activity
remote_host string Адрес клиента (если есть)
remote_port number Порт клиента
session_id string Уникальный идентификатор сессии
line_num number Порядковый номер записи внутри одной сессии
ps string Отображение процесса, как в команде ps
session_start string Время старта сессии
vxid string Виртуальный ID транзакции
txid string Обычный ID транзакции (если назначен)
error_severity string Уровень сообщения: LOG, WARNING, ERROR, FATAL и т.д.
state_code string Код SQLSTATE, крайне полезен для классификации ошибок
message string Основное сообщение - то, что вы привыкли видеть в текстовом логе
detail string Детали ошибки, например нарушенное ограничение
hint string Подсказка по исправлению
internal_query string Внутренний запрос, породивший ошибку
internal_position number Позиция ошибки во внутреннем запросе
context string Контекст (трассировка) ошибки
query string Текст запроса пользователя, если включен log_statement или сработал log_min_duration_statement

Поля из категории LOCATION (file, line, routine) также присутствуют отдельными ключами - они указывают исходный файл и функцию внутри PostgreSQL, где произошло событие.

Практический совет: для поиска ошибок чаще всего вы будете оперировать парой error_severity и state_code, для расследования сессионных проблем - session_id и session_start, а для аудита медленных запросов - query в сочетании с timestamp.

Что делать с JSON‑логами дальше: интеграция в стек мониторинга

Когда JSON‑файлы стабильно пишутся, следующий шаг - доставить их туда, где они принесут максимальную пользу.

Сбор и передача

Любой современный коллектор логов легко подхватывает файлы с расширением .json. Вы можете использовать:

  • Filebeat с нативным модулем для PostgreSQL или простым вводом filestream,
  • Vector - лёгкий агент, который парсит JSON прямо в источнике,
  • Logstash или Promtail - как часть уже существующего пайплайна.

Никакой сложной обработки не требуется: на входе чистый JSON, достаточно направить его в нужное хранилище. При комбинированном логировании stderr,jsonlog важно следить, чтобы сборщик забирал только .json или фильтровал файлы по расширению, иначе получите дубли.

Разбор в централизованных системах

В Elasticsearch JSON‑логи индексируются без дополнительных преобразований - каждое поле автоматически становится отдельным атрибутом документа. В Grafana Loki достаточно определить в promtail метку filename, а содержимое и так останется структурированным. Если вы складываете логи в ClickHouse, то прямая вставка строк через INSERT ... FORMAT JSONEachRow или материализованные колонки на основе JSONExtract работают отлично.

Ценность здесь не в конкретной системе, а в том, что из лога сразу уходит этап сложного парсинга. Готовые поля error_severity и state_code позволяют моментально строить панели «Топ ошибок по кодам» или «Количество ERROR за последний час».

Примеры полезных запросов и дашбордов (идеи)

Не привязываясь к инструменту, вот что становится доступным:

  • Срез по severity - подсчёт количества ERROR, FATAL, WARNING за период с группировкой по dbname.
  • Медленные запросы - если включён log_min_duration_statement, можно отфильтровать строки, где query не пустой, и вывести топ по времени выполнения (поле duration также доступно в JSON).
  • Активность пользователей - количество сессий по user и remote_host.
  • Анализ сессии - по session_id и session_start можно построить полный трек действий клиента вплоть до ошибки.

Такие дашборды не требуют «волшебных» цифр - достаточно корректной группировки и выбора временного окна.

Типичные трудности и их решение

Логи не пишутся: забыли logging_collector = on

Самая частая причина, когда после log_destination = 'jsonlog' файлы на диске не появляются. Проверьте:

logging_collector = on

Без этой строки логи будут уходить только в stderr и останутся под управлением внешнего супервизора (systemd, pg_ctl). Включение коллектора безопасно, но потребует pg_ctl reload.

JSON‑файл не появляется или пишется в stderr

Если logging_collector активен, но файл всё равно не создаётся, проверьте log_directory - путь должен существовать и быть доступен для записи процессу PostgreSQL. Ещё одна причина: конфликт в шаблоне log_filename. Убедитесь, что в маске нет символов, недопустимых в имени файла на вашей файловой системе, и что не происходит наложения с другими процессами.

Иногда кажется, что JSON‑логи пишутся в stderr, потому что сборщик показывает и то, и другое. При комбинированном режиме всегда смотрите в log_directory - там должен лежать отдельный файл с суффиксом .json.

Слишком много данных, рост дискового пространства

JSON немного более многословен, чем stderr, но разница не критична для большинства инсталляций. Если объём становится проблемой, используйте стандартные приёмы:

  • Уменьшите уровень логирования: log_min_messages = warning или error - для продового мониторинга этого часто достаточно.
  • Исключите вывод SQL‑запросов через log_statement = 'none' и поднимайте порог log_min_duration_statement до реально «тяжёлых» значений.
  • Настройте агрессивную ротацию по размеру и возрасту, а старые файлы архивируйте или удаляйте.
  • Отправляйте логи в централизованное хранилище и освобождайте локальный диск.

Точных данных о накладных расходах jsonlog по сравнению с stderr в процентах нет - они сильно зависят от характера нагрузки. В большинстве случаев выигрыш от структурирования перевешивает небольшое увеличение объёма.

FAQ: ответы на горячие вопросы

1. С какой версии PostgreSQL можно использовать jsonlog? Начиная с PostgreSQL 15. В более ранних версиях формат недоступен, и параметр log_destination = 'jsonlog' приведёт к ошибке.

2. Нужно ли перезагружать сервер после смены параметров? Нет, достаточно выполнить pg_ctl reload или вызвать SELECT pg_reload_conf(). Все параметры логирования перечитываются без прерывания обслуживания.

3. Можно ли оставить старый текстовый лог и одновременно писать JSON? Да, укажите log_destination = 'stderr,jsonlog'. В каталоге log_directory будут создаваться оба типа файлов. Это отличный способ мягкого перехода.

4. Как узнать имя текущего файла JSON‑логов? Воспользуйтесь функцией pg_current_logfile('jsonlog'). Она вернёт полный путь к актуальному файлу, включая название. Аналогично работает pg_current_logfile('stderr') для текстового лога.

5. Попадают ли в JSON‑лог медленные запросы и ошибки уровня STATEMENT? Да, если у вас настроен log_min_duration_statement или включён log_statement, то текст запроса окажется в поле query, а событие будет записано со severity LOG. Ошибки сервера и сообщения уровня STATEMENT также попадают в JSON с соответствующими кодами.

6. Как настроить ротацию JSON‑логов без внешних утилит? Используйте встроенные механизмы: задайте log_rotation_age (максимальное время жизни файла) и log_rotation_size (предельный размер). Можно также задействовать маски времени в log_filename, например postgresql-%H.json - тогда новый файл будет создаваться каждый час.

7. Что делать, если лог‑файл внезапно перестал обновляться? Сначала проверьте, не достигнут ли лимит ротации, и не смонтирован ли диск в read-only. Убедитесь, что процесс PostgreSQL не завис и что logging_collector не отключён динамически (хотя для него это нетипично). Если файл перестал расти, а новые записи не появляются, попробуйте принудительно переоткрыть логи через pg_rotate_logfile().

8. Безопасно ли хранить JSON‑логи с запросами пользователей? Сами по себе JSON‑логи - это просто файлы, их безопасность определяется уровнем доступа каталога log_directory. Если вы пишете в лог тексты запросов (log_statement или log_min_duration_statement), они окажутся в открытом виде. Ограничьте доступ к файлам средствами ОС и следите, чтобы централизованные системы сбора также защищали передаваемые данные. При необходимости маскируйте конфиденциальную информацию до записи или исключайте детальные запросы из логов на продуктивных базах.

Заключение: чистые логи - спокойный сон DBA

jsonlog - не просто очередная «галочка» в changelog’е PostgreSQL. Это прямой путь к тому, чтобы перестать тратить время на разбор текстовой каши и начать видеть реальное состояние сервера с одного взгляда. Пара дополнительных строк в конфигурации, и ваши логи превращаются в готовый источник данных для любого мониторингового стека.

Начните с комбинированного режима, протестируйте на неProduction-окружении, а затем делайте JSON‑логи основным форматом. Когда в три часа ночи вам понадобится понять, почему упало приложение, структурированный лог скажет всё сам - быстро и без регулярных выражений.

Источники

Это авторская статья, основанная на личном опыте и субъективном взгляде автора. Заметили ошибку или битую ссылку? Сообщите нам: info@codesrc.ru - мы оперативно исправим. Спасибо, что помогаете делать блог лучше.
Следите за нами в соцсетях:

Читайте также