Мониторинг долгих запросов PostgreSQL в Prometheus

Предположим, что у вас есть PostgreSQL (AWS RDS или классический PostgreSQL server), Prometheus, postgres exporter и alertmanager с Grafana.
Стоит задача присылать уведомления о том, что в Postgres подвис запрос. Причина и т.п. нас мало интересует. Нужно просто сказать всем, кому положено, что есть проблема и ее нужно решить.
Для этого нам понадобится немного допилить exporter кастомными метриками. Делается это отдельным файлом конфигурации. Пусть это будет /etc/queries.yaml.
pg_long_running_queries:
query: |
SELECT current_database(),
pid,
EXTRACT(EPOCH FROM age(clock_timestamp(), query_start)) AS duration_seconds,
state,
query
FROM pg_stat_activity
WHERE state = 'active' AND now() - query_start > interval '5 minutes';
metrics:
- current_database:
usage: "LABEL"
description: "Name of DataBase"
- duration_seconds:
usage: "GAUGE"
description: "Duration of long-running queries in seconds"
- pid:
usage: "LABEL"
description: "Process ID"
- state:
usage: "LABEL"
description: "Query state"
- query:
usage: "LABEL"
description: "SQL Query"
[Unit]
Description=Postgres exporter
After=network.target
[Service]
User=postgres
Group=postgres
Type=simple
EnvironmentFile=/etc/postgres_exporter.env
ExecStart=/usr/local/bin/postgres_exporter \
--config.file=/etc/postgres_exporter.yaml \
--auto-discover-databases \
--exclude-databases="rdsadmin,template0,template1,postgres,unused" \
--collector.stat_statements \
--collector.long_running_transactions \
--extend.query-path=/etc/queries.yaml
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
Конфиг самого exporter'a лежит в /etc/postgres_exporter.yaml и окружение в /etc/postgres_exporter.env.
Перезаупскаем postgres_exporter:
systemctl daemon-reload
service postgres_exporter restart
В результате мы в Prometheus должны увидеть метрику pg_long_running_queries_duration_seconds. По ней и строим вот такой алерт:
- alert: LongQueryDetected
expr: pg_long_running_queries_duration_seconds{query !~ "VACUUM ANALYZE .*"}
for: 5m
labels:
severity: critical
annotations:
summary: Long running query detected (instance {{ $labels.instance }})
description: "Long running query detected\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
Задача решена.