Adding a Threshold¶
Collecting data and judging it are separate steps. Once your check is registered — built-in or custom, no distinction — give it a threshold:
This is the only function for setting thresholds — seeding a built-in check's threshold, adding one for your own check, and later updating either are all just calls to this same function. A threshold is defined against the check only: exactly one per check, applying wherever the check runs, whichever suite runs it — suites decide what runs together, checks own what the results mean. It's an upsert: calling it again for the same check replaces the values in place. There's no protected "seeded" state — every one of the framework's own built-in thresholds was written by calling this exact function, and you can update any of them the same way. (Need two different sensitivities for the same metric? Copy the check and threshold the copy independently.)
- The soft, middle, and hard tiers — any combination may be set, matching your check's numeric direction. Direction is read from the check's own catalog record, not repeated here — a "lower is better" check breaches when the value exceeds a tier; "higher is better" breaches when it falls below one; "a specific target is the ideal" treats each tier as a maximum allowed distance from that ideal value.
- The boolean-breach-severity parameter is for
boolean-typed checks instead of numeric tiers: which severity a value that doesn't match the check's configured "pass" value maps to. - The consecutive-breaches parameter is debounce: require a chosen number of consecutive breaching runs before the breach counts as confirmed. The default is 1 (no debounce).
Beyond a plain numeric tier¶
Three optional comparator extensions cover the shapes a flat scalar tier can't — each still just parameters on this same one function, no custom code:
A jsonb check's payload — p_value_path + p_value_direction. Multi-metric checks have no single "value" to threshold, and previously always needed a custom evaluator. If the rule you actually want is "threshold one number inside the payload", extract it with a jsonpath instead:
SELECT pghf.set_threshold('X02-001',
p_value_path => '$.summary.max_lag_seconds'::jsonpath,
p_value_direction => 'lower_is_better', -- jsonb checks carry no direction metadata of their own
p_warn_value => '30'::jsonb, p_crit_value => '120'::jsonb);
The tiers then judge the extracted value exactly as they would a scalar check's. A path that matches nothing evaluates as not_evaluable, never an error. (A rule that needs several fields at once, or per-entity logic, still wants a custom evaluator — this is for the common one-number case.)
A text check — p_text_pass_pattern + p_text_breach_severity. The text counterpart of the boolean comparator: a POSIX regular expression the value must match, and the severity a mismatch maps to. Anchor with ^...$ for an exact match:
SELECT pghf.set_threshold('X01-002',
p_text_pass_pattern => '^(streaming|catchup)$',
p_text_breach_severity => 'critical');
Rate of change — p_delta_kind. 'absolute' or 'percent' makes the tiers judge the change since the check's previous collected sample instead of the value itself — "WAL grew by more than 500MB since the last run", "connection count jumped more than 40%":
Direction-aware: with a known bad direction (the check's own, or p_value_direction — delta composes with p_value_path), only worsening movement counts and improvement is simply ok; with no direction, magnitude either way is judged. The first-ever run has no prior sample and evaluates not_evaluable.
Evaluate a run once it's been collected:
CALL pghf.evaluate_run(p_run_id => '<run_id from execute_check_run>');
SELECT * FROM pghf.get_results_sql('<run_id from execute_check_run>');
The raw severity is what this one run's data says on its own; the confirmed severity is the raw severity after debounce has been applied. Use the confirmed severity for anything downstream — alerting, dashboards — the raw severity is mainly there so a debounce lookback (and you, while debugging) can see the un-smoothed signal underneath it.
Continue to Debounce: Requiring Consecutive Failures.