Running Checks End to End¶
For the full structure of what's seeded — the namespace, its 15 categories, all 175 built-in checks, and the seven ready-made cadence suites (seeded-1m through seeded-on-demand) — see the dedicated Catalog book. This chapter shows the common path: collect, evaluate, then read the results, using nothing but what's already there.
Running it end to end¶
Collect, evaluate, then read the results. Every command and its output below was run for real against a fresh install, with no custom checks registered. Any of the seeded suites works identically; this walkthrough uses seeded-1h, the hourly slice of the catalog (20 checks).
CALL pghf.execute_check_run(p_run_key => 'seeded-1h');
SELECT run_id FROM pghf.runs ORDER BY started_at DESC LIMIT 1;
-- 77b80891-5c2f-420b-844a-1d9692a233b4
("run_id" is a UUID — a long, randomly generated identifier chosen so that two different ones will, for all practical purposes, never clash. See the Glossary.)
All 20 of the suite's checks ran, landing:
The 2 skipped checks are this suite's two Spock-cluster checks reporting themselves as skipped on a server without the Spock extension — entirely expected on a fresh single-node install, and the same happens in every suite for checks depending on an extension that isn't there and for standby-only checks on a primary. A skipped result is the check correctly reporting "this doesn't apply here" — not a failure. (This framework also simply doesn't register checks that could never collect real data from inside a SQL session at all, in any configuration — client-side network probes, reads of the host's own filesystem, calls out to an external command-line tool. See the Licence book for exactly where these were removed and why.)
Now judge the collected data against the seeded thresholds:
CALL pghf.evaluate_run(p_run_id => '77b80891-5c2f-420b-844a-1d9692a233b4');
SELECT severity, count(*) FROM pghf.get_results_sql('77b80891-5c2f-420b-844a-1d9692a233b4') GROUP BY severity ORDER BY count(*) DESC;
skipped tracks the 2 skipped checks one-for-one — a real collection gap, never silently read as ok. not_evaluable is the 9 checks in this suite with no default threshold seeded (many of these report a structured breakdown with no single number to threshold; others are purely informational). Only the checks with a seeded threshold get a real verdict — 8 ok, and one genuine finding:
SELECT * FROM pghf.get_results_sql('77b80891-5c2f-420b-844a-1d9692a233b4', p_min_severity => 'warning');
severity | category_id | check_id | check_name | value | message
----------+-------------+------------+-----------------------------------------------+--------+----------------------------------------------
critical | PGHF11 | PGHF11-009 | Superuser login roles as % of all login roles | 100.00 | value 100.00 exceeds critical threshold 50
A real, useful result: on this fresh test cluster, postgres is the only login role, so 100% of login roles are superusers — exactly the kind of thing this framework exists to catch. p_min_severity => 'warning' is what an operator would actually use day to day: it works like a logging level, showing the tier you name and everything more severe, so everything below warning — noise on a healthy system — is left out. This is the query that belongs in a runbook or a notification job.
That's the entire lifecycle using nothing beyond what automatic seeding already provided — no namespace, category, check, or threshold was registered by hand. The other cadence suites run exactly the same way on their own schedules, and because evaluation history is one stream per check no matter which suite ran it, Alert Status merges them all into a single current-state view. See How Threshold Evaluation Works for the full severity scale, tuning these defaults, and debounce (requiring more than one bad result in a row before reporting a breach); see Scheduling Health Checks for running this on a recurring basis.
One call instead of two: pghf.run_and_evaluate() runs execute_check_run() and evaluate_run() together, in a single call, with the same parameters as execute_check_run():
CALL pghf.run_and_evaluate(p_run_key => 'seeded-1h');
-- p_run_id
-- --------------------------------------
-- 0e4da442-3637-4fae-be4a-69d942613771
This produces identical results to the two separate calls above — the same 20 checks collected and evaluated, the same finding. Reading the results back out is still a separate step either way. This must be called as a standalone CALL statement on its own — not from inside a function, and not inside an explicit transaction block — because it internally commits twice, once for each stage it wraps.
Everything above runs the checks sequentially, one at a time, in your own session — the default. A suite can also opt in to running its checks in parallel through the pg_relay extension's workers, which changes when a run is considered finished — see Parallel Execution via pg_relay.
Continue to How Threshold Evaluation Works.