Мониторинг PostgreSQL с помощью Proto Observability

Сбор метрик и логов баз данных, таблиц, индексов, транзакций и запросов PostgreSQL.

На этой странице:

Сбор метрик PostgreSQL

Интеграция postgres подключается к PostgreSQL по обычному wire-протоколу (порт 5432), а не через JMX — поэтому образ агента используется обычный, без суффикса -jmx. Проверка читает системные представления pg_stat_*, pg_class, pg_locks, pg_settings и (опционально) pg_stat_statements, поэтому пользователю агента достаточно прав read-only.

Часть семейств метрик включается отдельными флагами в instances::

ФлагЧто добавляет
relationsметрики на уровне таблиц и индексов (postgresql_table_size, postgresql_seq_scans, postgresql_index_scans, postgresql_live_rows и т.п.), а также postgresql_locks
collect_function_metricspostgresql_function_* из pg_stat_user_functions
collect_count_metricspostgresql_table_count (число пользовательских таблиц)
collect_activity_metricspostgresql_active_queries, postgresql_waiting_queries, postgresql_transactions_* из pg_stat_activity
collect_database_size_metricspostgresql_database_size (включено по умолчанию)
collect_bloat_metricspostgresql_table_bloat, postgresql_index_bloat
collect_wal_metricspostgresql_wal_age
dbm: trueсбор метрик уровня SQL-запросов: метрики запросов postgresql_queries_*, postgresql_transactions_duration_*, sample-планы (требует pg_stat_statements и helper-функцию explain_statement)

Конфигурация PostgreSQL

Пользователь для мониторинга

Создайте пользователя с правами read-only для агента ProtoOBP:

  • Для PostgreSQL версии 10 и выше — встроенная роль pg_monitor уже включает pg_read_all_settings, pg_read_all_stats и pg_stat_scan_tables, то есть всё необходимое для pg_stat_* и pg_stat_statements:

    CREATE USER protoobp WITH PASSWORD '<PASSWORD>';
    GRANT pg_monitor TO protoobp;
    
  • Для более старых версий PostgreSQL роли pg_monitor нет — выдайте права на представления статистики напрямую:

    CREATE USER protoobp WITH PASSWORD '<PASSWORD>';
    -- выдайте SELECT на нужные представления статистики
    -- (pg_stat_database, pg_stat_bgwriter, pg_stat_activity, …)
    GRANT SELECT ON pg_stat_database, pg_stat_bgwriter, pg_stat_activity TO protoobp;
    

pg_stat_statements (метрики запросов)

Семейство postgresql_queries_* (метрики уровня запроса — счётчик выполнений, суммарное время, прочитанные/записанные блоки и т.п.) собирается из расширения pg_stat_statements и доступно только при включённом сборе метрик уровня SQL-запросов (dbm: true).

  1. Добавьте библиотеку в shared_preload_libraries (требует рестарта сервера) — например, в postgresql.conf:

    shared_preload_libraries = 'pg_stat_statements'
    pg_stat_statements.track = all
    

    В Docker это удобно сделать флагом командной строки:

    services:
      postgresql:
        image: postgres:16
        command:
          - postgres
          - -c
          - shared_preload_libraries=pg_stat_statements
          - -c
          - pg_stat_statements.track=all
    
  2. Создайте расширение в той базе, которую мониторите:

    CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
    
  3. (Опционально, для sample-планов выполнения запросов) создайте схему protoobp и SECURITY DEFINER функцию explain_statement — она позволяет агенту получать планы выполнения запросов:

    CREATE SCHEMA IF NOT EXISTS protoobp;
    GRANT USAGE ON SCHEMA protoobp TO protoobp;
    
    CREATE OR REPLACE FUNCTION protoobp.explain_statement(
       l_query text,
       OUT explain JSON
    )
    RETURNS SETOF JSON AS
    $$
    DECLARE
       curs REFCURSOR;
       plan JSON;
    BEGIN
       OPEN curs FOR EXECUTE pg_catalog.concat('EXPLAIN (FORMAT JSON) ', l_query);
       FETCH curs INTO plan;
       CLOSE curs;
       RETURN QUERY SELECT plan;
    END;
    $$
    LANGUAGE 'plpgsql'
    RETURNS NULL ON NULL INPUT
    SECURITY DEFINER;
    

    Если такая схема уже создана под другим именем, переименовывать её не обязательно — достаточно указать pg_stat_statements_view / application_name в конфиге проверки.

Конфигурация ProtoOBP агента

Если агент запускается в виде службы на хосте

  1. Создайте файл /etc/protoobp-agent/conf.d/postgres.d/conf.yaml:

    init_config:
    
    instances:
      - host: localhost
        port: 5432
        username: protoobp
        password: "<PASSWORD>"
        # По умолчанию dbname — postgres
        dbname: "<DB_NAME>"
        # Метрики уровня таблиц и индексов + postgresql.locks.
        # relation_regex: ".*" — для всех таблиц; можно ограничить списком.
        relations:
          - relation_regex: ".*"
        collect_function_metrics: true
        collect_count_metrics: true
        collect_activity_metrics: true
        collect_database_size_metrics: true
        # Включите для метрик запросов postgresql.queries.* (нужен pg_stat_statements):
        # dbm: true
    
  2. Перезапустите ProtoOBP агента: systemctl restart protoobp-agent.

  3. Выполните проверку работы агента и убедитесь, что в разделе postgres нет ошибок.

Если агент запускается в виде Docker контейнера

  1. Добавьте autodiscovery-лейблы к Docker контейнеру с PostgreSQL.

    • в docker-compose.yaml

      labels:
        com.protoobp.ad.check_names: '["postgres"]'
        com.protoobp.ad.init_configs: "[{}]"
        com.protoobp.ad.instances: '[{"host": "%%host%%", "port": 5432, "username": "protoobp", "password": "<PASSWORD>", "dbname": "<DB_NAME>", "relations": [{"relation_regex": ".*"}], "collect_function_metrics": true, "collect_count_metrics": true, "collect_activity_metrics": true, "collect_database_size_metrics": true}]'
      
    • или в Dockerfile

      LABEL "com.protoobp.ad.check_names"='["postgres"]'
      LABEL "com.protoobp.ad.init_configs"='[{}]'
      LABEL "com.protoobp.ad.instances"='[{"host": "%%host%%", "port": 5432, "username": "protoobp", "password": "<PASSWORD>", "dbname": "<DB_NAME>", "relations": [{"relation_regex": ".*"}], "collect_function_metrics": true, "collect_count_metrics": true, "collect_activity_metrics": true, "collect_database_size_metrics": true}]'
      
  2. Примените изменения лейблов для контейнера с PostgreSQL (перезапуском контейнера), а также перезапустите контейнер с агентом ProtoOBP.

  3. Выполните проверку работы агента и убедитесь, что в разделе postgres нет ошибок.

Проверка

Убедитесь, что проверка запустилась и собирает метрики:

docker exec protoobp-agent agent status | grep -A 12 "postgres ("

Ожидаемый вывод — instance со статусом [OK] и ненулевыми Metric Samples (пример на PostgreSQL 16):

    postgres (12.5.1)
    -----------------
      Instance ID: postgres:55565625862af0c1 [OK]
      Configuration Source: container:docker://5a926dda...
      Total Runs: 32
      Metric Samples: Last Run: 74, Total: 2,246
      Events: Last Run: 0, Total: 0
      Service Checks: Last Run: 1, Total: 32
      Average Execution Time : 22ms
      metadata:
        version.major: 16
        version.minor: 13

Полный список собранных серий с тегами (двойной прогон, чтобы увидеть и rate-метрики):

docker exec protoobp-agent agent check postgres --check-rate

В выводе присутствуют ~60 уникальных метрик postgresql_* — в том числе postgresql_connections, postgresql_commits / postgresql_rollbacks, postgresql_rows_inserted / rows_updated / rows_deleted / rows_returned / rows_fetched / rows_hot_updated, postgresql_buffer_hit / postgresql_disk_read, postgresql_heap_blocks_read / heap_blocks_hit / index_blocks_read / index_blocks_hit / toast_blocks_read / toast_blocks_hit, postgresql_seq_scans / seq_rows_read / index_scans / index_rel_scans / index_rows_read / index_rows_fetched, postgresql_bgwriter_* (checkpoints_timed / checkpoints_requested / buffers_checkpoint / buffers_clean / buffers_backend / buffers_alloc / write_time / sync_time / …), postgresql_table_size / index_size / total_size / database_size, postgresql_live_rows / dead_rows, postgresql_vacuumed / autovacuumed / analyzed / autoanalyzed, postgresql_temp_bytes / temp_files, postgresql_deadlocks, postgresql_transactions_open / transactions_idle_in_transaction, postgresql_active_queries / waiting_queries / active_waiting_queries, postgresql_archiver_archived_count / failed_count, postgresql_max_connections / percent_usage_connections / before_xid_wraparound / db_count / table_count. Теги на сериях: db, schema, table, index (на per-table / per-index метриках), port, service, env, server и метки образа (docker_image, image_name, image_tag, short_image).

Собираемые метрики

Большинство метрик имеют тип gauge (мгновенное значение на момент сбора). Часть метрик — типа rate (postgresql_commits, postgresql_rollbacks, postgresql_rows_*, postgresql_buffer_hit, postgresql_disk_read, postgresql_deadlocks, postgresql_temp_bytes, postgresql_temp_files, postgresql_function_*): это скорость в секунду, рассчитанная агентом из кумулятивных счётчиков PostgreSQL. Метрики с суффиксом .count (а также postgresql_bgwriter_*, postgresql_wal_* и т.п.) — кумулятивные счётчики типа count (монотонно растут от старта сервера); для дашбордов применяйте PromQL rate(... [5m]).

Лейблы

Общие (на всех метриках)

Добавляются агентом и ProtoOBP backend’ом:

ЛейблЗначение
hostХост, на котором работает агент
portПорт PostgreSQL (5432)
serviceТег service (через com.protoobp.tags.service или POBP_TAGS)
envТег env
docker_imageПолный ref образа контейнера (например, postgres:16)
image_nameИмя образа без тега
image_tagТег образа
short_imageКороткое имя образа
Специфичные для PostgreSQL
ЛейблГде появляетсяПример
dbпочти все метрики (имя базы данных)demo
schemaметрики уровня таблиц/индексов (relations)demo
tableметрики уровня таблиц/индексов (relations)events
indexметрики уровня индексов (relations)events_kind_idx
lock_modepostgresql_locksAccessShareLock
lock_typepostgresql_locksrelation
grantedpostgresql_locks (блокировка выдана или в ожидании)true / false
appметрики активности и запросов (application_name)psql
userметрики активности и запросовprotoobp
query_signatureметрики запросов postgresql_queries_* (при dbm: true)4f2d...
partition_ofpostgresql_relation_* для партицийevents
phaseпрогресс-метрики postgresql_vacuum_* / analyze.*scanning heap

Соединения и сессии

Несут лейбл db.

Имя метрикиТипЕдиницаОписание
postgresql_connectionsgaugeconnectionКоличество активных соединений с этой базой данных
postgresql_max_connectionsgaugeconnectionМаксимально разрешённое число клиентских подключений
postgresql_percent_usage_connectionsgaugefractionДоля используемых подключений от максимума
postgresql_sessions_countcountsessionВсего установленных сессий с этой базой
postgresql_sessions_active_timecountmillisecondВремя выполнения SQL-запросов в этой базе
postgresql_sessions_idle_in_transaction_timecountmillisecondВремя простоя сессий «в транзакции»
postgresql_sessions_session_timecountmillisecondСуммарное время сессий с этой базой
postgresql_sessions_abandonedcountsessionСессии, завершённые из-за потери соединения с клиентом
postgresql_sessions_fatalcountsessionСессии, завершённые фатальными ошибками
postgresql_sessions_killedcountsessionСессии, завершённые вмешательством оператора
postgresql_uptimegaugesecondВремя работы сервера в секундах
postgresql_runninggaugeКоличество работающих инстансов (1, если сервер доступен)
postgresql_before_xid_wraparoundgaugetransactionСколько транзакций осталось до transaction ID wraparound

Транзакции

Несут лейбл db.

Имя метрикиТипЕдиницаОписание
postgresql_commitsratetransaction/secondСкорость зафиксированных (commit) транзакций
postgresql_rollbacksratetransaction/secondСкорость откаченных (rollback) транзакций
postgresql_deadlocksratelock/secondСкорость обнаруженных тупиковых ситуаций (deadlock)
postgresql_deadlocks_countcountlockКумулятивное число обнаруженных deadlock’ов

Доступ к данным (на уровне базы)

Несут лейбл db. postgresql_disk_read и postgresql_buffer_hit — основная пара для расчёта cache hit ratio. rows_inserted / rows_updated / rows_deleted / rows_hot_updated появляются при включённом relations.

Имя метрикиТипЕдиницаОписание
postgresql_disk_readrateblock/secondСкорость дисковых блоков, прочитанных в этой базе
postgresql_buffer_hitratehit/secondСкорость попаданий в буферный кэш (блок нашёлся в shared buffers)
postgresql_rows_returnedraterow/secondСкорость строк, возвращённых запросами (просмотрено)
postgresql_rows_fetchedraterow/secondСкорость строк, реально извлечённых запросами
postgresql_rows_insertedraterow/secondСкорость вставленных строк (требует relations)
postgresql_rows_updatedraterow/secondСкорость обновлённых строк (требует relations)
postgresql_rows_deletedraterow/secondСкорость удалённых строк (требует relations)
postgresql_rows_hot_updatedraterow/secondСкорость HOT-обновлений (без обновления индексов; требует relations)
postgresql_temp_bytesratebyte/secondСкорость записи во временные файлы запросами этой базы
postgresql_temp_filesratefile/secondСкорость создания временных файлов запросами этой базы
postgresql_blk_read_timecountmillisecondВремя чтения блоков бэкендами (при track_io_timing = on)
postgresql_blk_write_timecountmillisecondВремя записи блоков бэкендами (при track_io_timing = on)
postgresql_checksums_enabledcount1, с тегом `enabled:true
postgresql_checksums_checksum_failurescountЧисло сбоев контрольных сумм в этой базе
postgresql_conflicts_lock / .deadlock / .snapshot / .bufferpin / .tablespacecountqueryЗапросы, отменённые из-за конфликтов восстановления (на standby)

Bgwriter / checkpointer

Тип count (кумулятивные счётчики). Без лейбла db — относятся ко всему кластеру.

Имя метрикиЕдиницаОписание
postgresql_bgwriter_checkpoints_timedЗапланированных контрольных точек выполнено
postgresql_bgwriter_checkpoints_requestedЗапрошенных (внеплановых) контрольных точек выполнено
postgresql_bgwriter_buffers_checkpointБуферов записано во время контрольных точек
postgresql_bgwriter_buffers_cleanБуферов записано фоновым писателем (bgwriter)
postgresql_bgwriter_maxwritten_cleanРаз фоновый писатель прервал очистку из-за слишком большого числа записанных буферов
postgresql_bgwriter_buffers_backendbufferБуферов записано непосредственно бэкендами
postgresql_bgwriter_buffers_backend_fsyncРаз бэкенд выполнял собственный fsync вместо фонового писателя
postgresql_bgwriter_buffers_allocВыделенных буферов
postgresql_bgwriter_write_timemillisecondВремя обработки контрольных точек, потраченное на запись файлов
postgresql_bgwriter_sync_timemillisecondВремя обработки контрольных точек, потраченное на синхронизацию файлов
postgresql_control_checkpoint_delaysecondВремя с момента последней контрольной точки
postgresql_control_timeline_idТекущий timeline id

WAL

Имя метрикиТипЕдиницаОписание
postgresql_wal_bytescountbyteСгенерировано WAL, байт
postgresql_wal_recordscountrecordСгенерировано WAL-записей
postgresql_wal_full_page_imagescountpageСгенерировано full page images в WAL
postgresql_wal_buffers_fullcountРаз WAL сбрасывался на диск из-за переполнения WAL-буферов
postgresql_wal_writecountwriteРаз WAL-буферы записывались на диск
postgresql_wal_synccountРаз WAL-файлы синхронизировались на диск
postgresql_wal_write_timecountmillisecondВремя записи WAL-буферов на диск (при track_wal_io_timing = on)
postgresql_wal_sync_timecountmillisecondВремя синхронизации WAL-файлов на диск (при track_wal_io_timing = on)
postgresql_wal_countgaugeКоличество WAL-файлов на диске
postgresql_wal_sizegaugebyteСуммарный размер WAL-файлов на диске
postgresql_wal_agegaugesecondВозраст самого старого WAL-файла (требует collect_wal_metrics)
postgresql_archiver_archived_countcountWAL-файлов успешно заархивировано
postgresql_archiver_failed_countcountНеудачных попыток архивации WAL-файлов

Размер баз данных

Имя метрикиТипЕдиницаОписание
postgresql_database_sizegaugebyteДисковое пространство, используемое этой базой (db)
postgresql_db_countgaugeitemКоличество доступных баз данных

Метрики на уровне таблицы

Включаются параметром relations. Несут лейблы db, schema, table.

Имя метрикиТипЕдиницаОписание
postgresql_seq_scansgaugescan/secondПоследовательных сканирований по этой таблице
postgresql_seq_rows_readgaugerow/secondЖивых строк, прочитанных при последовательных сканированиях
postgresql_index_scansgaugescan/secondИндексных сканирований по этой таблице (с тегом по индексу)
postgresql_index_rel_scansgaugescan/secondОбщее число индексных сканирований по этой таблице
postgresql_index_rows_fetchedgaugerow/secondЖивых строк, извлечённых при индексных сканированиях (с тегом по индексу)
postgresql_index_rel_rows_fetchedgaugerow/secondЖивых строк, извлечённых при индексных сканированиях этой таблицы
postgresql_live_rowsgaugerowОценочное число живых строк
postgresql_dead_rowsgaugerowОценочное число «мёртвых» строк (кандидаты на vacuum)
postgresql_heap_blocks_readgaugeblock/secondДисковых блоков, прочитанных из этой таблицы
postgresql_heap_blocks_hitgaugehit/secondПопаданий в буфер при чтении этой таблицы
postgresql_index_blocks_readgaugeblock/secondДисковых блоков, прочитанных из всех индексов этой таблицы
postgresql_index_blocks_hitgaugehit/secondПопаданий в буфер во всех индексах этой таблицы
postgresql_table_sizegaugebyteДисковое пространство таблицы вместе с TOAST (без индексов)
postgresql_index_sizegaugebyteСуммарный размер всех индексов этой таблицы
postgresql_total_sizegaugebyteПолный размер таблицы (данные + индексы + TOAST)
postgresql_relation_sizegaugebyteРазмер собственно таблицы (без TOAST, FSM, VM, индексов)
postgresql_toast_sizegaugebyteРазмер TOAST-таблицы, прикреплённой к этой таблице
postgresql_individual_index_sizegaugebyteДисковое пространство конкретного индекса
postgresql_vacuumedcountСколько раз таблица вакуумирована вручную
postgresql_autovacuumedcountСколько раз таблица вакуумирована демоном autovacuum
postgresql_analyzedcountСколько раз таблица проанализирована вручную
postgresql_autoanalyzedcountСколько раз таблица проанализирована демоном autovacuum
postgresql_last_vacuum_agegaugesecondВремя с момента последнего ручного VACUUM
postgresql_last_autovacuum_agegaugesecondВремя с момента последнего autovacuum
postgresql_last_analyze_agegaugesecondВремя с момента последнего ручного ANALYZE
postgresql_last_autoanalyze_agegaugesecondВремя с момента последнего autoanalyze
postgresql_table_countgaugetableЧисло пользовательских таблиц в этой базе (тег schema; требует collect_count_metrics)
postgresql_relation_pagesgaugeРазмер таблицы в страницах (оценка планировщика; тег partition_of)
postgresql_relation_tuplesgaugeЧисло живых строк в таблице (оценка планировщика)
postgresql_relation_all_visiblegaugeСтраниц, помеченных all-visible в visibility map
postgresql_relation_xmingaugeTransaction ID последнего изменения записи в pg_class
postgresql_locksgaugelockАктивных блокировок (теги lock_mode, lock_type, schema, table, granted)

Прогресс-метрики долгих операций (несут теги db, table, phase и др.): postgresql_vacuum_heap_blks_scanned / .heap_blks_total / .heap_blks_vacuumed / .index_vacuum_count / .num_dead_tuples / .max_dead_tuples, postgresql_analyze_sample_blks_scanned / .sample_blks_total / .child_tables_done / .child_tables_total / .ext_stats_computed / .ext_stats_total, postgresql_cluster_vacuum_*, postgresql_create_index_* (PostgreSQL 12+).

Метрики на уровне индекса

Включаются параметром relations. Несут лейблы db, schema, table, index.

Имя метрикиТипЕдиницаОписание
postgresql_index_scansgaugescan/secondИндексных сканирований этого индекса
postgresql_index_rows_readgaugerow/secondЗаписей индекса, возвращённых при сканированиях этого индекса
postgresql_index_rows_fetchedgaugerow/secondЖивых строк, извлечённых через этот индекс
postgresql_individual_index_sizegaugebyteДисковое пространство этого индекса

TOAST

Включаются параметром relations. Несут лейблы db, schema, table.

Имя метрикиТипЕдиницаОписание
postgresql_toast_blocks_readgaugeblock/secondДисковых блоков, прочитанных из TOAST-таблицы
postgresql_toast_blocks_hitgaugehit/secondПопаданий в буфер в TOAST-таблице
postgresql_toast_index_blocks_readgaugeblock/secondДисковых блоков, прочитанных из индекса TOAST-таблицы
postgresql_toast_index_blocks_hitgaugehit/secondПопаданий в буфер в индексе TOAST-таблицы
postgresql_toast_live_rows / .dead_rowsgaugeЖивых / «мёртвых» строк в TOAST-таблице
postgresql_toast_rows_inserted / .rows_fetched / .rows_deletedcountВставлено / извлечено / удалено строк в TOAST-таблице
postgresql_toast_index_scanscountИндексных сканирований по TOAST-таблице
postgresql_toast_vacuumed / .autovacuumedcountСколько раз TOAST-таблица вакуумирована вручную / автоматически
postgresql_toast_last_vacuum_age / .last_autovacuum_agegaugesecondВремя с момента последнего vacuum / autovacuum TOAST-таблицы

Bloat (collect_bloat_metrics)

Имя метрикиТипЕдиницаОписание
postgresql_table_bloatgaugepercentОценочный процент разбухания таблицы (теги db, schema, table)
postgresql_index_bloatgaugepercentОценочный процент разбухания индекса (теги db, schema, table, index)

Активность (collect_activity_metrics)

Из pg_stat_activity. По умолчанию несут теги db, app, user.

Имя метрикиТипЕдиницаОписание
postgresql_active_queriesgaugeАктивных запросов в этой базе
postgresql_active_waiting_queriesgaugeАктивных запросов в состоянии ожидания
postgresql_waiting_queriesgaugeОжидающих запросов в этой базе
postgresql_transactions_opengaugetransactionОткрытых транзакций в этой базе
postgresql_transactions_idle_in_transactiongaugetransactionТранзакций в состоянии «idle in transaction»
postgresql_transactions_duration_maxgaugenanosecondВозраст самой долгой выполняющейся транзакции (при dbm: true)
postgresql_transactions_duration_sumgaugenanosecondСумма возрастов всех выполняющихся транзакций (при dbm: true)
postgresql_activity_xact_start_agegaugesecondВозраст самой старой активной транзакции
postgresql_activity_backend_xid_age / .backend_xmin_agegaugetransactionВозраст xid / xmin-горизонта самого старого бэкенда

Функции (collect_function_metrics)

Из pg_stat_user_functions. Несут теги db, schema, function.

Имя метрикиТипЕдиницаОписание
postgresql_function_callsrateСкорость вызовов функции
postgresql_function_total_timerateВремя в этой функции и всех вызываемых ею функциях
postgresql_function_self_timerateВремя в самой функции (без вложенных вызовов)

Репликация

Доступны при наличии соответствующих представлений (на primary / standby).

Имя метрикиТипЕдиницаОписание
postgresql_replication_delaygaugesecondТекущая задержка репликации в секундах (PostgreSQL 9.1+)
postgresql_replication_delay_bytesgaugebyteТекущая задержка репликации в байтах (PostgreSQL 9.2+)
postgresql_replication_wal_write_laggaugesecondЛаг между локальным flush WAL и подтверждением записи на standby
postgresql_replication_wal_flush_laggaugesecondЛаг между локальным flush WAL и подтверждением flush на standby
postgresql_replication_wal_replay_laggaugesecondЛаг между локальным flush WAL и подтверждением применения на standby
postgresql_replication_backend_xmin_agegaugeВозраст xmin-горизонта standby (по hot_standby_feedback)
postgresql_replication_slot_xmin_age / .catalog_xmin_agegaugetransactionВозраст транзакций, удерживаемых replication slot’ом (теги slot_name, slot_type, …)
postgresql_replication_slot_restart_delay_bytes / .confirmed_flush_delay_bytesgaugebyteОбъём WAL, удерживаемый слотом / лаг подтверждения flush для логического слота
postgresql_replication_slot_spill_* / .stream_* / .total_*countСтатистика логического декодирования по слоту (PostgreSQL 14+)
postgresql_wal_receiver_connectedgaugeСостояние WAL receiver’а (1 + тег status)
postgresql_wal_receiver_last_msg_receipt_age / .last_msg_send_age / .latest_end_age / .received_timelinegaugeВозраст последнего сообщения от WAL sender’а / номер timeline
postgresql_subscription_*gauge/countСостояние и статистика логических подписок (PostgreSQL 12/14/15+)

Метрики запросов (pg_stat_statements)

Доступны только при dbm: true и установленном pg_stat_statements. Тип count (кумулятивные), несут теги query_signature, db, userduration.*user, db, app).

Имя метрикиЕдиницаОписание
postgresql_queries_countqueryВсего выполнений запроса для query_signature/db/user
postgresql_queries_timenanosecondСуммарное время выполнения запроса
postgresql_queries_rowsrowВсего строк, извлечённых или затронутых запросом
postgresql_queries_shared_blks_hit / .shared_blks_read / .shared_blks_dirtied / .shared_blks_writtenblockОбращения к кэшу / чтения / «загрязнения» / записи разделяемых блоков
postgresql_queries_local_blks_hit / .local_blks_read / .local_blks_dirtied / .local_blks_writtenblockТо же для локальных блоков
postgresql_queries_temp_blks_read / .temp_blks_writtenblockЧтения / записи временных блоков
postgresql_queries_blk_read_time / .blk_write_timenanosecondВремя чтения / записи блоков для запроса
postgresql_queries_duration_max / .duration.sumnanosecondВозраст самого долгого / сумма возрастов выполняющихся запросов
postgresql_pg_stat_statements_deallocРаз pg_stat_statements вытеснял редкие запросы (достигнут pg_stat_statements.max)

Группа метрик ввода-вывода уровня кластера, доступная для PostgreSQL 16+ и только при dbm: true: postgresql_io_reads / .writes / .hits / .evictions / .extends / .fsyncs и соответствующие *_time (теги backend_type, context, object).

Ключевые метрики для дашбордов и алертов

Доступность сервера

  • Отсутствие свежих серий по host/port или postgresql_running == 0 — алерт: PostgreSQL недоступен или агент не может подключиться.
  • postgresql_percent_usage_connections приближается к 1.0 — пул соединений на исходе; новые клиенты получат too many connections.
  • postgresql_before_xid_wraparound резко уменьшается — приближение к transaction ID wraparound (риск аварийной остановки кластера).

Транзакции и нагрузка

  • rate(postgresql_commits) vs rate(postgresql_rollbacks) — высокая доля rollback’ов = проблемы в приложении или дедлоки.
  • postgresql_deadlocks (rate) > 0 — алерт: пересекающиеся блокировки.
  • postgresql_locks с granted=false per table — запросы стоят в ожидании блокировок.
  • postgresql_transactions_idle_in_transaction стабильно > 0 — «висящие» транзакции держат блокировки и тормозят vacuum.
  • postgresql_activity_xact_start_age (или transactions.duration.max) большое — долгая транзакция, удерживающая ресурсы.

Кэш и ввод-вывод

  • Cache hit ratio = rate(postgresql_buffer_hit) / (rate(postgresql_buffer_hit) + rate(postgresql_disk_read)) — устойчиво < 0.95–0.99 на OLTP-нагрузке = не хватает shared_buffers или плохой план.
  • postgresql_temp_bytes / postgresql_temp_files (rate) растут — сортировки и хэши не помещаются в work_mem, спиливаются на диск.
  • rate(postgresql_blk_read_time) высокое (при track_io_timing=on) — узкое место в дисковом I/O.

VACUUM / bloat

  • postgresql_dead_rows per table стабильно растёт при низком rate(postgresql_autovacuumed) — autovacuum не успевает (тюнинг порогов или ручной VACUUM).
  • postgresql_last_autovacuum_age per table слишком большой — таблица давно не вакуумировалась.
  • postgresql_table_bloat / postgresql_index_bloat (при collect_bloat_metrics) > 30–50 % — кандидаты на VACUUM FULL / REINDEX.

Контрольные точки и WAL

  • Высокая доля rate(postgresql_bgwriter_checkpoints_requested) относительно rate(postgresql_bgwriter_checkpoints_timed) — контрольные точки запускаются по объёму WAL слишком часто; увеличьте max_wal_size / checkpoint_timeout.
  • postgresql_bgwriter_buffers_backend доминирует над buffers_clean / buffers_checkpoint — bgwriter не справляется, бэкенды пишут грязные буферы сами.
  • rate(postgresql_wal_bytes) — объём генерируемого WAL; всплески = массовые записи, влияет на репликацию и архивацию.
  • postgresql_archiver_failed_count (rate) > 0 — archive_command падает, WAL-файлы копятся.

Репликация (если используется)

  • postgresql_replication_delay / postgresql_replication_wal_replay_lag — лаг standby; алерт при превышении SLA.
  • postgresql_replication_slot_restart_delay_bytes растёт у неактивного слота — «осиротевший» слот удерживает WAL, диск primary заполняется.
  • postgresql_wal_receiver_connected с status:disconnected — standby потерял связь с primary.

Рост данных

  • postgresql_database_size per db, postgresql_total_size per table — тренд роста для capacity planning.
  • postgresql_index_size существенно больше postgresql_table_size при низком postgresql_index_scans — неиспользуемые индексы.

Запросы (при dbm: true)

  • topk по rate(postgresql_queries_time) per query_signature — самые «тяжёлые» нормализованные запросы.
  • rate(postgresql_queries_temp_blks_written) per query_signature > 0 — запрос регулярно спиливает на диск.
  • postgresql_queries_duration_max per user/db большое — конкретный пользователь/приложение крутит долгий запрос.

Сбор логов PostgreSQL

Логи PostgreSQL собираются ProtoOBP агентом и отправляются в бэкенд ProtoOBP. Здесь — только специфичные для PostgreSQL настройки. Включение логов на стороне агента (logs_enabled, logs_pobp_url) описано в Получение данных логов.

Конфигурация ProtoOBP агента

Если агент запускается в виде службы на хосте

Дополните уже существующий /etc/protoobp-agent/conf.d/postgres.d/conf.yaml (тот же файл, в котором лежит instances: для метрик) блоком logs::

logs:
  - type: file
    path: /var/log/postgresql/*.log
    source: postgresql
    service: postgresql
    log_processing_rules:
      - type: multi_line
        name: log_start_with_date
        pattern: \d{4}-\d{2}-\d{2}

Если включён logging_collector = on, используйте путь из log_directory (по умолчанию $PGDATA/log/*.log).

Перезапустите агента: systemctl restart protoobp-agent.

Если агент запускается в виде Docker контейнера

Шаг 1 — включите сбор логов в самом агенте через переменные окружения и смонтируйте директорию JSON-логов docker-демона:

services:
  protoobp-agent:
    environment:
      POBP_LOGS_ENABLED: "true"
      POBP_LOGS_CONFIG_USE_HTTP: "true"
      POBP_LOGS_CONFIG_LOGS_POBP_URL: <protoobp-backend>:<port>
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      # Прямое чтение JSON-лог файлов docker-демона быстрее,
      # чем тянуть их через Docker socket API.
      - /var/lib/docker/containers:/var/lib/docker/containers:ro

Шаг 2 — добавьте лейбл com.protoobp.ad.logs к контейнеру PostgreSQL. Агент подхватит stdout/stderr контейнера и пометит записи указанными source и service:

services:
  postgresql:
    labels:
      com.protoobp.ad.logs: '[{"source": "postgresql", "service": "postgresql", "log_processing_rules": [{"type": "multi_line", "name": "log_start_with_date", "pattern": "\\d{4}-\\d{2}-\\d{2}"}]}]'

Проверка

В выводе agent status в разделе Logs Agent должен быть источник с Source: postgresql, Status: OK и ненулевым BytesRead:

docker exec protoobp-agent agent status | grep -A 60 'Logs Agent'

Пример вывода:

Logs Agent
==========
    Reliable: Sending compressed logs in HTTPS to <protoobp-backend> on port 443
    BytesSent: 2.947246e+06
    LogsProcessed: 4062
    LogsSent: 4032

  docker
  ------
    - Type: file
      Path: /var/lib/docker/containers/5a926dda.../5a926dda...-json.log
      Service: postgresql
      Source: postgresql
      Status: OK
      BytesRead: 1.7736e+06
      Lines Combined: 5348
      MultiLine matches: 3902

Ненулевые Lines Combined / MultiLine matches подтверждают, что правило multi_line склеивает многострочные записи (тексты запросов, STATEMENT:-блоки) в одну. У источника типа «JSON-файл docker-контейнера» поле Status обычно OK, но даже если оно отображается как Pending — ориентируйтесь на BytesRead и LogsProcessed.