Мониторинг PostgreSQL с помощью Proto Observability
На этой странице:
- Сбор метрик PostgreSQL
- Конфигурация PostgreSQL
- Конфигурация ProtoOBP агента
- Проверка
- Собираемые метрики
- Лейблы
- Соединения и сессии
- Транзакции
- Доступ к данным (на уровне базы)
- Bgwriter / checkpointer
- WAL
- Размер баз данных
- Метрики на уровне таблицы
- Метрики на уровне индекса
- TOAST
- Bloat (collect_bloat_metrics)
- Активность (collect_activity_metrics)
- Функции (collect_function_metrics)
- Репликация
- Метрики запросов (pg_stat_statements)
- Ключевые метрики для дашбордов и алертов
- Сбор логов 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_metrics | postgresql_function_* из pg_stat_user_functions |
collect_count_metrics | postgresql_table_count (число пользовательских таблиц) |
collect_activity_metrics | postgresql_active_queries, postgresql_waiting_queries, postgresql_transactions_* из pg_stat_activity |
collect_database_size_metrics | postgresql_database_size (включено по умолчанию) |
collect_bloat_metrics | postgresql_table_bloat, postgresql_index_bloat |
collect_wal_metrics | postgresql_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;
`relations` и пользовательские таблицы
Если включён relations, агент дополнительно запрашивает размеры
пользовательских таблиц (pg_total_relation_size(...) и т.п.). Роль
pg_monitor покрывает представления pg_stat_user_tables / pg_statio_*, но
не сами таблицы — выдайте protoobp ещё и SELECT на нужные схемы:
GRANT USAGE ON SCHEMA <schema> TO protoobp;
GRANT SELECT ON ALL TABLES IN SCHEMA <schema> TO protoobp;
ALTER DEFAULT PRIVILEGES IN SCHEMA <schema> GRANT SELECT ON TABLES TO protoobp;
pg_stat_statements (метрики запросов)
Семейство postgresql_queries_* (метрики уровня запроса — счётчик выполнений,
суммарное время, прочитанные/записанные блоки и т.п.) собирается из расширения
pg_stat_statements и доступно только при включённом сборе метрик уровня
SQL-запросов (dbm: true).
Добавьте библиотеку в
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Создайте расширение в той базе, которую мониторите:
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;(Опционально, для 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 агента
Если агент запускается в виде службы на хосте
Создайте файл
/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Перезапустите ProtoOBP агента:
systemctl restart protoobp-agent.Выполните проверку работы агента и убедитесь, что в разделе
postgresнет ошибок.
Обратите внимание
Для отображения нового хоста СУБД следует обновить страницу браузера целиком (кнопкаОбновить в правом верхнем углу веб-консоли обновляет только значения
метрик на дашборде, но не список серверов).Если агент запускается в виде Docker контейнера
Добавьте autodiscovery-лейблы к Docker контейнеру с PostgreSQL.
в
docker-compose.yamllabels: 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}]'или в
DockerfileLABEL "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}]'
Примените изменения лейблов для контейнера с PostgreSQL (перезапуском контейнера), а также перезапустите контейнер с агентом ProtoOBP.
Выполните проверку работы агента и убедитесь, что в разделе
postgresнет ошибок.
Контейнер агента
Контейнер агента должен находиться в той же docker network, что и PostgreSQL. Также агенту нужен смонтированный/var/run/docker.sock:/var/run/docker.sock:ro
для autodiscovery контейнеров. Образ агента — обычный, без суффикса -jmx.Обратите внимание
Для отображения нового хоста СУБД следует обновить страницу браузера целиком (кнопкаОбновить в правом верхнем углу веб-консоли обновляет только значения
метрик на дашборде, но не список серверов).Проверка
Убедитесь, что проверка запустилась и собирает метрики:
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_mode | postgresql_locks | AccessShareLock |
lock_type | postgresql_locks | relation |
granted | postgresql_locks (блокировка выдана или в ожидании) | true / false |
app | метрики активности и запросов (application_name) | psql |
user | метрики активности и запросов | protoobp |
query_signature | метрики запросов postgresql_queries_* (при dbm: true) | 4f2d... |
partition_of | postgresql_relation_* для партиций | events |
phase | прогресс-метрики postgresql_vacuum_* / analyze.* | scanning heap |
Соединения и сессии
Несут лейбл db.
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
postgresql_connections | gauge | connection | Количество активных соединений с этой базой данных |
postgresql_max_connections | gauge | connection | Максимально разрешённое число клиентских подключений |
postgresql_percent_usage_connections | gauge | fraction | Доля используемых подключений от максимума |
postgresql_sessions_count | count | session | Всего установленных сессий с этой базой |
postgresql_sessions_active_time | count | millisecond | Время выполнения SQL-запросов в этой базе |
postgresql_sessions_idle_in_transaction_time | count | millisecond | Время простоя сессий «в транзакции» |
postgresql_sessions_session_time | count | millisecond | Суммарное время сессий с этой базой |
postgresql_sessions_abandoned | count | session | Сессии, завершённые из-за потери соединения с клиентом |
postgresql_sessions_fatal | count | session | Сессии, завершённые фатальными ошибками |
postgresql_sessions_killed | count | session | Сессии, завершённые вмешательством оператора |
postgresql_uptime | gauge | second | Время работы сервера в секундах |
postgresql_running | gauge | Количество работающих инстансов (1, если сервер доступен) | |
postgresql_before_xid_wraparound | gauge | transaction | Сколько транзакций осталось до transaction ID wraparound |
Транзакции
Несут лейбл db.
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
postgresql_commits | rate | transaction/second | Скорость зафиксированных (commit) транзакций |
postgresql_rollbacks | rate | transaction/second | Скорость откаченных (rollback) транзакций |
postgresql_deadlocks | rate | lock/second | Скорость обнаруженных тупиковых ситуаций (deadlock) |
postgresql_deadlocks_count | count | lock | Кумулятивное число обнаруженных deadlock’ов |
Доступ к данным (на уровне базы)
Несут лейбл db. postgresql_disk_read и postgresql_buffer_hit — основная
пара для расчёта cache hit ratio. rows_inserted / rows_updated /
rows_deleted / rows_hot_updated появляются при включённом relations.
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
postgresql_disk_read | rate | block/second | Скорость дисковых блоков, прочитанных в этой базе |
postgresql_buffer_hit | rate | hit/second | Скорость попаданий в буферный кэш (блок нашёлся в shared buffers) |
postgresql_rows_returned | rate | row/second | Скорость строк, возвращённых запросами (просмотрено) |
postgresql_rows_fetched | rate | row/second | Скорость строк, реально извлечённых запросами |
postgresql_rows_inserted | rate | row/second | Скорость вставленных строк (требует relations) |
postgresql_rows_updated | rate | row/second | Скорость обновлённых строк (требует relations) |
postgresql_rows_deleted | rate | row/second | Скорость удалённых строк (требует relations) |
postgresql_rows_hot_updated | rate | row/second | Скорость HOT-обновлений (без обновления индексов; требует relations) |
postgresql_temp_bytes | rate | byte/second | Скорость записи во временные файлы запросами этой базы |
postgresql_temp_files | rate | file/second | Скорость создания временных файлов запросами этой базы |
postgresql_blk_read_time | count | millisecond | Время чтения блоков бэкендами (при track_io_timing = on) |
postgresql_blk_write_time | count | millisecond | Время записи блоков бэкендами (при track_io_timing = on) |
postgresql_checksums_enabled | count | 1, с тегом `enabled:true | |
postgresql_checksums_checksum_failures | count | Число сбоев контрольных сумм в этой базе | |
postgresql_conflicts_lock / .deadlock / .snapshot / .bufferpin / .tablespace | count | query | Запросы, отменённые из-за конфликтов восстановления (на 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_backend | buffer | Буферов записано непосредственно бэкендами |
postgresql_bgwriter_buffers_backend_fsync | Раз бэкенд выполнял собственный fsync вместо фонового писателя | |
postgresql_bgwriter_buffers_alloc | Выделенных буферов | |
postgresql_bgwriter_write_time | millisecond | Время обработки контрольных точек, потраченное на запись файлов |
postgresql_bgwriter_sync_time | millisecond | Время обработки контрольных точек, потраченное на синхронизацию файлов |
postgresql_control_checkpoint_delay | second | Время с момента последней контрольной точки |
postgresql_control_timeline_id | Текущий timeline id |
WAL
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
postgresql_wal_bytes | count | byte | Сгенерировано WAL, байт |
postgresql_wal_records | count | record | Сгенерировано WAL-записей |
postgresql_wal_full_page_images | count | page | Сгенерировано full page images в WAL |
postgresql_wal_buffers_full | count | Раз WAL сбрасывался на диск из-за переполнения WAL-буферов | |
postgresql_wal_write | count | write | Раз WAL-буферы записывались на диск |
postgresql_wal_sync | count | Раз WAL-файлы синхронизировались на диск | |
postgresql_wal_write_time | count | millisecond | Время записи WAL-буферов на диск (при track_wal_io_timing = on) |
postgresql_wal_sync_time | count | millisecond | Время синхронизации WAL-файлов на диск (при track_wal_io_timing = on) |
postgresql_wal_count | gauge | Количество WAL-файлов на диске | |
postgresql_wal_size | gauge | byte | Суммарный размер WAL-файлов на диске |
postgresql_wal_age | gauge | second | Возраст самого старого WAL-файла (требует collect_wal_metrics) |
postgresql_archiver_archived_count | count | WAL-файлов успешно заархивировано | |
postgresql_archiver_failed_count | count | Неудачных попыток архивации WAL-файлов |
Размер баз данных
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
postgresql_database_size | gauge | byte | Дисковое пространство, используемое этой базой (db) |
postgresql_db_count | gauge | item | Количество доступных баз данных |
Метрики на уровне таблицы
Включаются параметром relations. Несут лейблы db, schema, table.
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
postgresql_seq_scans | gauge | scan/second | Последовательных сканирований по этой таблице |
postgresql_seq_rows_read | gauge | row/second | Живых строк, прочитанных при последовательных сканированиях |
postgresql_index_scans | gauge | scan/second | Индексных сканирований по этой таблице (с тегом по индексу) |
postgresql_index_rel_scans | gauge | scan/second | Общее число индексных сканирований по этой таблице |
postgresql_index_rows_fetched | gauge | row/second | Живых строк, извлечённых при индексных сканированиях (с тегом по индексу) |
postgresql_index_rel_rows_fetched | gauge | row/second | Живых строк, извлечённых при индексных сканированиях этой таблицы |
postgresql_live_rows | gauge | row | Оценочное число живых строк |
postgresql_dead_rows | gauge | row | Оценочное число «мёртвых» строк (кандидаты на vacuum) |
postgresql_heap_blocks_read | gauge | block/second | Дисковых блоков, прочитанных из этой таблицы |
postgresql_heap_blocks_hit | gauge | hit/second | Попаданий в буфер при чтении этой таблицы |
postgresql_index_blocks_read | gauge | block/second | Дисковых блоков, прочитанных из всех индексов этой таблицы |
postgresql_index_blocks_hit | gauge | hit/second | Попаданий в буфер во всех индексах этой таблицы |
postgresql_table_size | gauge | byte | Дисковое пространство таблицы вместе с TOAST (без индексов) |
postgresql_index_size | gauge | byte | Суммарный размер всех индексов этой таблицы |
postgresql_total_size | gauge | byte | Полный размер таблицы (данные + индексы + TOAST) |
postgresql_relation_size | gauge | byte | Размер собственно таблицы (без TOAST, FSM, VM, индексов) |
postgresql_toast_size | gauge | byte | Размер TOAST-таблицы, прикреплённой к этой таблице |
postgresql_individual_index_size | gauge | byte | Дисковое пространство конкретного индекса |
postgresql_vacuumed | count | Сколько раз таблица вакуумирована вручную | |
postgresql_autovacuumed | count | Сколько раз таблица вакуумирована демоном autovacuum | |
postgresql_analyzed | count | Сколько раз таблица проанализирована вручную | |
postgresql_autoanalyzed | count | Сколько раз таблица проанализирована демоном autovacuum | |
postgresql_last_vacuum_age | gauge | second | Время с момента последнего ручного VACUUM |
postgresql_last_autovacuum_age | gauge | second | Время с момента последнего autovacuum |
postgresql_last_analyze_age | gauge | second | Время с момента последнего ручного ANALYZE |
postgresql_last_autoanalyze_age | gauge | second | Время с момента последнего autoanalyze |
postgresql_table_count | gauge | table | Число пользовательских таблиц в этой базе (тег schema; требует collect_count_metrics) |
postgresql_relation_pages | gauge | Размер таблицы в страницах (оценка планировщика; тег partition_of) | |
postgresql_relation_tuples | gauge | Число живых строк в таблице (оценка планировщика) | |
postgresql_relation_all_visible | gauge | Страниц, помеченных all-visible в visibility map | |
postgresql_relation_xmin | gauge | Transaction ID последнего изменения записи в pg_class | |
postgresql_locks | gauge | lock | Активных блокировок (теги 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_scans | gauge | scan/second | Индексных сканирований этого индекса |
postgresql_index_rows_read | gauge | row/second | Записей индекса, возвращённых при сканированиях этого индекса |
postgresql_index_rows_fetched | gauge | row/second | Живых строк, извлечённых через этот индекс |
postgresql_individual_index_size | gauge | byte | Дисковое пространство этого индекса |
TOAST
Включаются параметром relations. Несут лейблы db, schema, table.
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
postgresql_toast_blocks_read | gauge | block/second | Дисковых блоков, прочитанных из TOAST-таблицы |
postgresql_toast_blocks_hit | gauge | hit/second | Попаданий в буфер в TOAST-таблице |
postgresql_toast_index_blocks_read | gauge | block/second | Дисковых блоков, прочитанных из индекса TOAST-таблицы |
postgresql_toast_index_blocks_hit | gauge | hit/second | Попаданий в буфер в индексе TOAST-таблицы |
postgresql_toast_live_rows / .dead_rows | gauge | Живых / «мёртвых» строк в TOAST-таблице | |
postgresql_toast_rows_inserted / .rows_fetched / .rows_deleted | count | Вставлено / извлечено / удалено строк в TOAST-таблице | |
postgresql_toast_index_scans | count | Индексных сканирований по TOAST-таблице | |
postgresql_toast_vacuumed / .autovacuumed | count | Сколько раз TOAST-таблица вакуумирована вручную / автоматически | |
postgresql_toast_last_vacuum_age / .last_autovacuum_age | gauge | second | Время с момента последнего vacuum / autovacuum TOAST-таблицы |
Bloat (collect_bloat_metrics)
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
postgresql_table_bloat | gauge | percent | Оценочный процент разбухания таблицы (теги db, schema, table) |
postgresql_index_bloat | gauge | percent | Оценочный процент разбухания индекса (теги db, schema, table, index) |
Активность (collect_activity_metrics)
Из pg_stat_activity. По умолчанию несут теги db, app, user.
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
postgresql_active_queries | gauge | Активных запросов в этой базе | |
postgresql_active_waiting_queries | gauge | Активных запросов в состоянии ожидания | |
postgresql_waiting_queries | gauge | Ожидающих запросов в этой базе | |
postgresql_transactions_open | gauge | transaction | Открытых транзакций в этой базе |
postgresql_transactions_idle_in_transaction | gauge | transaction | Транзакций в состоянии «idle in transaction» |
postgresql_transactions_duration_max | gauge | nanosecond | Возраст самой долгой выполняющейся транзакции (при dbm: true) |
postgresql_transactions_duration_sum | gauge | nanosecond | Сумма возрастов всех выполняющихся транзакций (при dbm: true) |
postgresql_activity_xact_start_age | gauge | second | Возраст самой старой активной транзакции |
postgresql_activity_backend_xid_age / .backend_xmin_age | gauge | transaction | Возраст xid / xmin-горизонта самого старого бэкенда |
Функции (collect_function_metrics)
Из pg_stat_user_functions. Несут теги db, schema, function.
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
postgresql_function_calls | rate | Скорость вызовов функции | |
postgresql_function_total_time | rate | Время в этой функции и всех вызываемых ею функциях | |
postgresql_function_self_time | rate | Время в самой функции (без вложенных вызовов) |
Репликация
Доступны при наличии соответствующих представлений (на primary / standby).
| Имя метрики | Тип | Единица | Описание |
|---|---|---|---|
postgresql_replication_delay | gauge | second | Текущая задержка репликации в секундах (PostgreSQL 9.1+) |
postgresql_replication_delay_bytes | gauge | byte | Текущая задержка репликации в байтах (PostgreSQL 9.2+) |
postgresql_replication_wal_write_lag | gauge | second | Лаг между локальным flush WAL и подтверждением записи на standby |
postgresql_replication_wal_flush_lag | gauge | second | Лаг между локальным flush WAL и подтверждением flush на standby |
postgresql_replication_wal_replay_lag | gauge | second | Лаг между локальным flush WAL и подтверждением применения на standby |
postgresql_replication_backend_xmin_age | gauge | Возраст xmin-горизонта standby (по hot_standby_feedback) | |
postgresql_replication_slot_xmin_age / .catalog_xmin_age | gauge | transaction | Возраст транзакций, удерживаемых replication slot’ом (теги slot_name, slot_type, …) |
postgresql_replication_slot_restart_delay_bytes / .confirmed_flush_delay_bytes | gauge | byte | Объём WAL, удерживаемый слотом / лаг подтверждения flush для логического слота |
postgresql_replication_slot_spill_* / .stream_* / .total_* | count | Статистика логического декодирования по слоту (PostgreSQL 14+) | |
postgresql_wal_receiver_connected | gauge | Состояние WAL receiver’а (1 + тег status) | |
postgresql_wal_receiver_last_msg_receipt_age / .last_msg_send_age / .latest_end_age / .received_timeline | gauge | Возраст последнего сообщения от WAL sender’а / номер timeline | |
postgresql_subscription_* | gauge/count | Состояние и статистика логических подписок (PostgreSQL 12/14/15+) |
Метрики запросов (pg_stat_statements)
Доступны только при dbm: true и установленном pg_stat_statements. Тип
count (кумулятивные), несут теги query_signature, db, user (а
duration.* — user, db, app).
| Имя метрики | Единица | Описание |
|---|---|---|
postgresql_queries_count | query | Всего выполнений запроса для query_signature/db/user |
postgresql_queries_time | nanosecond | Суммарное время выполнения запроса |
postgresql_queries_rows | row | Всего строк, извлечённых или затронутых запросом |
postgresql_queries_shared_blks_hit / .shared_blks_read / .shared_blks_dirtied / .shared_blks_written | block | Обращения к кэшу / чтения / «загрязнения» / записи разделяемых блоков |
postgresql_queries_local_blks_hit / .local_blks_read / .local_blks_dirtied / .local_blks_written | block | То же для локальных блоков |
postgresql_queries_temp_blks_read / .temp_blks_written | block | Чтения / записи временных блоков |
postgresql_queries_blk_read_time / .blk_write_time | nanosecond | Время чтения / записи блоков для запроса |
postgresql_queries_duration_max / .duration.sum | nanosecond | Возраст самого долгого / сумма возрастов выполняющихся запросов |
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)vsrate(postgresql_rollbacks)— высокая доля rollback’ов = проблемы в приложении или дедлоки.postgresql_deadlocks(rate)> 0— алерт: пересекающиеся блокировки.postgresql_locksсgranted=falsepertable— запросы стоят в ожидании блокировок.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_rowspertableстабильно растёт при низкомrate(postgresql_autovacuumed)— autovacuum не успевает (тюнинг порогов или ручнойVACUUM).postgresql_last_autovacuum_agepertableслишком большой — таблица давно не вакуумировалась.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_sizeperdb,postgresql_total_sizepertable— тренд роста для capacity planning.postgresql_index_sizeсущественно большеpostgresql_table_sizeпри низкомpostgresql_index_scans— неиспользуемые индексы.
Запросы (при dbm: true)
topkпоrate(postgresql_queries_time)perquery_signature— самые «тяжёлые» нормализованные запросы.rate(postgresql_queries_temp_blks_written)perquery_signature> 0— запрос регулярно спиливает на диск.postgresql_queries_duration_maxperuser/dbбольшое — конкретный пользователь/приложение крутит долгий запрос.
Сбор логов PostgreSQL
Логи PostgreSQL собираются ProtoOBP агентом и отправляются в бэкенд ProtoOBP.
Здесь — только специфичные для PostgreSQL настройки. Включение логов на стороне
агента (logs_enabled, logs_pobp_url) описано в
Получение данных логов.
Куда PostgreSQL пишет логи
По умолчанию (logging_collector = off) сервер пишет в stderr. При установке
из пакета это обычно перенаправляется в файл вроде
/var/log/postgresql/postgresql-16-main.log; в контейнере stderr процесса
становится логом контейнера. Если включён logging_collector = on, PostgreSQL
сам пишет файлы в $PGDATA/log/ (или каталог из log_directory) — тогда
указывайте маску *.log оттуда.
Для осмысленного содержимого лога полезно включить:
log_min_duration_statement = 250ms # логировать медленные запросы (или 0 — все)
log_checkpoints = on
log_lock_waits = on
log_autovacuum_min_duration = 0
log_line_prefix = '%m [%p] %q%u@%d ' # запись начинается с timestamp
log_line_prefix, начинающийся с %m (или %t), даёт записи вида
2026-05-12 10:00:00.123 UTC [42] user@db … — именно на эту дату опирается
правило multi_line.
Конфигурация 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}"}]}]'
Только нужные контейнеры
Если в агенте не задана переменнаяPOBP_LOGS_CONFIG_CONTAINER_COLLECT_ALL=true,
агент собирает логи только тех контейнеров, на которых есть лейбл
com.protoobp.ad.logs.Multi-line
При log_line_prefix, начинающемся с %m/%t, каждая запись лога PostgreSQL
начинается с метки времени YYYY-MM-DD HH:MM:SS.mmm TZ …. Правило
log_processing_rules с type: multi_line склеивает следующие за ней строки
(многострочные STATEMENT:/QUERY:-блоки, тексты длинных запросов, отчёты
autovacuum) в одну логическую запись. Без этого правила каждая строка попала бы
в ProtoOBP как отдельная запись.
Если в log_line_prefix нет даты в начале (например, он начинается с [%p]),
поменяйте pattern на тот префикс, с которого реально начинается запись, либо
добавьте %m в начало log_line_prefix.
Проверка
В выводе 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.