-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpgwd.conf.example
More file actions
220 lines (213 loc) · 10.3 KB
/
Copy pathpgwd.conf.example
File metadata and controls
220 lines (213 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# /etc/pgwd/pgwd.conf — pgwd config (YAML)
# Copy to /etc/pgwd/pgwd.conf and adjust.
# Use databases: for one or more Postgres (required; even for a single target).
# When config file is loaded, env vars (PGWD_*) are ignored. CLI flags override.
#
# RECOMMENDED: Use daemon mode (interval > 0) for sqlite, http, resolution notifications,
# and hysteresis. One-shot/timer mode runs once per tick — no history, no /metrics, no resolution.
#
# YAML ↔ CLI mapping (CLI overrides config):
# client → -client
# interval → -interval
# dry_run → -dry-run
# databases[].url → (config only). Override: -db-url + -interval 0 = one-shot against that URL only.
# databases[].stale_age → -db-stale-age (when single target)
# databases[].threshold.* → -db-threshold-* (when single target)
#
# CLI -db-url override (one-shot): with config that has databases:, passing -db-url and -interval 0
# runs against that single URL only (ignores databases from config for that run).
# kube.* → -kube-*
# notifications.* → -notifications-*
# CLI-only: -config, -force-notification, -test-max-connections, -validate-k8s-access,
# -export-metrics-format, -export-metrics-destination
# -----------------------------------------------------------------------------
# Instance identity (required when multiple pgwd instances run)
# -----------------------------------------------------------------------------
client: "prod-db-primary"
# -----------------------------------------------------------------------------
# Behavior
# -----------------------------------------------------------------------------
interval: 60
dry_run: true
log_level: info # info (default) or debug; debug = verbose dry-run stats
# Optional anonymous usage (daemon mode only; interval > 0):
# enable_collector: false # opt-in — default off
# enable_update_check: true # opt-out GitHub release check — default on
#
# When enable_collector is true, pgwd POSTs once per daemon start to:
# https://collect.gghstats.com/a1b2c3d4e5f6a7b8
# Example JSON body (no secrets — boolean feature flags only):
# {
# "version": "1.0.0",
# "commit": "abc1234",
# "build_date": "2026-07-18T12:00:00Z",
# "hash": "a1b2c3d4e5f67890",
# "features": {
# "multi_db": false,
# "uses_level_mode": true,
# "long_query_enabled": false,
# "has_slack": true,
# "has_loki": true,
# "has_kube_postgres": false,
# "has_kube_loki": false,
# "has_sqlite_store": true,
# "has_sql_metrics_store": false,
# "has_http_listen": true,
# "confirm_alert_gt_1": false,
# "confirm_ok_gt_1": false,
# "dry_run": false
# }
# }
# Never sent: DSN/URL, hostnames, client, webhooks, paths, secrets.
#
# When enable_update_check is true (default), pgwd GETs:
# https://api.github.com/repos/hrodrig/pgwd/releases/latest
# No pgwd config leaves the host; only public release tag for semver compare.
# See README "Anonymous usage" and SPECIFICATIONS.md §3.
# -----------------------------------------------------------------------------
# Database connection and thresholds (databases: canonical; db: removed in 1.0)
# -----------------------------------------------------------------------------
# Each entry: url (required), optional client, stale_age, default_threshold_percent, threshold.
# client: optional; defaults to base client + "-" + db name from URL path (NOT the hostname).
# If two URLs use the same path db name on different hosts, set explicit distinct clients
# or SQLite history / hysteresis / resolution will collide (key is client+cluster+database).
# kube.postgres / -kube-postgres is NOT supported with databases: (multi-DB = direct URLs only).
#
databases:
- url: postgres://user:pass@localhost:5432/mydb
# client: "prod-db-primary-mydb" # optional
stale_age: 0
default_threshold_percent: 80
threshold:
idle: 0
levels: "75,85,95" # 3-tier: attention, alert, danger
stale: 0
# Long-running queries (state=active, query age). Requires sqlite.path or metrics_store.
# long_query_min_seconds: 300 # 0 = off
# long_query_cooldown_seconds: 3600 # min time between long_query alerts per target (default 3600 if min set)
# long_query_min_count: 1 # alert when count >= N
# Multi-DB example (uncomment and adjust). Each url may use a different user:password.
# In-cluster: inject URLs from Secrets at deploy (Helm/Kustomize) — docs/use-cases.md UC-5.
# Outside cluster: N port-forwards + 127.0.0.1 URLs — docs/use-cases.md UC-6.
# Cannot combine with kube.postgres in one config. See docs/use-cases.md.
# databases:
# - url: postgres://user_a:pass_a@host1:5432/prod
# client: "monitor-01-prod"
# stale_age: 0
# threshold:
# idle: 0
# levels: "75,85,95"
# stale: 0
# - url: postgres://user:pass@host2:5432/analytics
# client: "monitor-01-analytics"
# threshold:
# levels: "80,90,98" # per-db override
# - url: postgres://user:pass@host3:5432/replica
# # no client → use base client + "-" + db name from URL
# -----------------------------------------------------------------------------
# SQLite & state (for resolution notifications and /metrics)
# -----------------------------------------------------------------------------
# REQUIRES daemon mode (interval > 0). One-shot/timer: no history, no resolution, no /metrics.
# sqlite:
# path: /var/lib/pgwd/pgwd.db # state and metrics history
# max_metrics: 10000 # FIFO eviction when exceeded
# stale_age: 300 # optional; seconds for stale count in store (0 = use databases[].stale_age)
#
# Optional: persist metrics to PostgreSQL or MySQL instead of SQLite (same FIFO semantics; max rows: sqlite.max_metrics).
# TimescaleDB: use driver postgres with a DSN to your Timescale instance (no separate pgwd driver).
# metrics_store:
# driver: postgres # or mysql, postgresql (alias), sqlite (requires sqlite.path)
# dsn: "postgres://user:pass@host:5432/pgwd_metrics?sslmode=disable"
# # MySQL example: "user:pass@tcp(host:3306)/pgwd_metrics?parseTime=true"
# CSV export reads the configured backend via internal/metricsstore.
# One-shot CSV: pgwd -config ... -export-metrics-format csv -export-metrics-destination /path/out.csv
#
# -----------------------------------------------------------------------------
# State stability (hysteresis)
# -----------------------------------------------------------------------------
# confirm_alert: 2 # consecutive "bad" checks before sending alert (avoid brief spikes)
# confirm_ok: 2 # consecutive "ok" checks before "returned to normal" resolution notification
#
# -----------------------------------------------------------------------------
# HTTP server (/metrics, /healthz for Kubernetes probes). REQUIRES daemon mode.
# -----------------------------------------------------------------------------
# http:
# listen: ":8080"
# base_path: "/api/pgwd/v1" # paths are relative to this
# healthz_path: "/healthz" # → /api/pgwd/v1/healthz (always open for probes)
# metrics_path: "/metrics" # → /api/pgwd/v1/metrics
# metrics_token: "" # OPT-IN: leave empty for anonymous /metrics (default)
# metrics_basic_user: "" # OPT-IN: basic auth for /metrics only (both user+password required)
# metrics_basic_password: ""
#
# In-cluster Prometheus / Grafana Alloy: leave metrics_token and metrics_basic_* empty.
# ServiceMonitor / PodMonitor scrapes work without credentials (same as before 0.9.x).
# Enable token or basic auth only when http.listen is reachable beyond a trusted network
# (VM, port-forward, wide bind). See contrib/k8s/README.md#http-metrics-privacy-opt-in.
# Bind to loopback or use NetworkPolicy when the port is not cluster-internal only.
#
# -----------------------------------------------------------------------------
# Kubernetes (optional)
# -----------------------------------------------------------------------------
# Two modes:
# - pgwd INSIDE K8s (Deployment): use databases[].url with in-cluster DNS
# (e.g. postgres://...@postgres.default.svc.cluster.local:5432/mydb).
# No kubectl. No kube.postgres.
# - pgwd OUTSIDE K8s (VM, cron): use kube.postgres + port-forward (client-go, no kubectl).
#
# DISCOVER_MY_PASSWORD was REMOVED in 0.9.x. Migration (copy-paste recipes):
# docs/kubernetes-passwords.md
# Ready-made outside-cluster profile: contrib/profiles/kube-prod.yml
# Wrapper (cron): contrib/k8s/pgwd-kube-run.sh | RBAC: contrib/k8s/rbac-outside-cluster.yaml
#
kube:
context: ""
local_port: 5432
loki: ""
loki_local_port: 3100
loki_remote_port: 3100
# Outside cluster: read password or full DSN from Secret (no pods/exec). See docs/kubernetes-passwords.md
password_from_secret:
namespace: ""
name: ""
key: password # or "url" for a full postgres:// DSN in the Secret
postgres: ""
# -----------------------------------------------------------------------------
# Notifications
# -----------------------------------------------------------------------------
notifications:
loki:
url: ""
bearer_token: ""
labels: ""
org_id: ""
slack:
webhook: ""
# PagerDuty Events API v2 (optional)
pagerduty:
enabled: false
routing_key: ""
severity: warning # default when event has no level mapping; events map danger/connect_failure → critical, alert → warning, attention/resolution/test → info
source: pgwd
# Microsoft Teams incoming webhook (optional)
teams:
enabled: false
webhook_url: ""
# Generic webhook with optional JWT headers and HMAC signing (optional)
generic:
enabled: false
webhook_url: ""
json_key: text
headers: {} # e.g. Authorization: "Bearer eyJ..."
extra_fields: {} # merged into default JSON payload
body_template: "" # Go template; must render valid JSON. Vars: Message, Threshold, Level, Total, Active, Idle, MaxConn, Cluster, Client, Database, Namespace, EventType
hmac_secret: ""
hmac_header: X-Pgwd-Signature
# Shared outbound HTTP retry for all notifiers (Slack, Loki, PagerDuty, Teams, generic)
retry:
max_attempts: 3
initial_backoff: 1s
max_backoff: 10s
# Re-send connection-threshold alerts every interval while the bad state persists (v1.0 spam).
# Default false: notify on enter / escalation / de-escalation only.
# repeat_while_firing: false