Files
selfheal-lab-gitops/vm/postgres-common/queries.yaml
T
seon bc8a8fbc97 fix(postgres): compute replication lag without the idle-primary artifact
upstream replication 컬렉터는 수신 LSN != 재생 LSN이면 now()-마지막 트랜잭션 재생 시각을 지연으로
보고한다. replica 재시작 직후에는 수신 LSN이 세그먼트 시작점(재생 LSN보다 작음)에 머물러 유휴
프라이머리에서 지연이 무한히 커진다(실측 116초→281초, 트랜잭션 1건 뒤 0). DbReplicationLag가
pending으로 올라갔다. 수신 LSN <= 재생 LSN이면 0으로 보는 custom query로 교체하고 upstream
replication 컬렉터를 끈다. pg_replication_is_replica도 같은 쿼리에서 낸다.
2026-10-08 02:01:56 +09:00

28 lines
1.7 KiB
YAML

# Custom postgres_exporter queries (Alloy prometheus.exporter.postgres custom_queries_config_path).
# Metric name = <key>_<column>.
#
# pg_replication_lag_seconds / pg_replication_is_replica replace the upstream "replication" collector (disabled in
# config.alloy). The upstream formula reports now() - pg_last_xact_replay_timestamp() whenever receive LSN != replay LSN;
# right after a replica restart the receive LSN sits at the segment start below the replay LSN until new WAL arrives,
# so on an idle primary the lag grows without bound (observed 2026-10-08: 116 s -> 281 s, back to 0 after one
# transaction). Treating receive <= replay as "fully applied" removes that artifact; real lag (replay paused, slow
# apply under load) still shows because receive runs ahead of replay.
pg_replication:
query: "SELECT CASE WHEN NOT pg_is_in_recovery() THEN 0 WHEN pg_last_wal_receive_lsn() <= pg_last_wal_replay_lsn() THEN 0 ELSE GREATEST(0, EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp()))) END AS lag_seconds, CASE WHEN pg_is_in_recovery() THEN 1 ELSE 0 END AS is_replica"
master: true
metrics:
- lag_seconds:
usage: "GAUGE"
description: "Replication lag behind the primary in seconds (0 when every received byte is replayed)"
- is_replica:
usage: "GAUGE"
description: "1 when the server is in recovery (replica)"
# pg_is_wal_replay_paused (used by the DbReplicationLag rule, design 4.3): not in any upstream collector.
pg_is_wal_replay:
query: "SELECT CASE WHEN pg_is_in_recovery() AND pg_is_wal_replay_paused() THEN 1 ELSE 0 END AS paused"
master: true
metrics:
- paused:
usage: "GAUGE"
description: "1 when this server is a replica and WAL replay is paused"