feat(settings): configurable monitoring thresholds
Move the hardcoded warn/crit cutoffs into Settings -> Thresholds (DB-backed, live, no restart). New thresholds.* keys + to_thresholds_cfg() + a threshold_style(value, kind) jinja global that reads them; latency reuses the existing ping good/warn keys, uptime is direction-aware (floors). Replace the _macros metric_style/uptime_style macros (now removed) with the global across Hosts-Overview, host_agent fleet + panel, Uptime/SLA widget, and the ping page uptime column — all now honor the configured cutoffs. Uptime keeps its green 'good' look when not degraded. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -68,6 +68,16 @@ DEFAULTS: dict[str, Any] = {
|
||||
"ansible.max_concurrent_runs": 3,
|
||||
"ping.threshold.good_ms": 50,
|
||||
"ping.threshold.warn_ms": 200,
|
||||
# Degraded/critical cutoffs for metric coloring (warn=amber, crit=red).
|
||||
# cpu/mem/disk/load are percentages (load is load-per-core %); temp in °C.
|
||||
# uptime is "higher is better" so its warn/crit are floors. Ping latency
|
||||
# reuses ping.threshold.good_ms/warn_ms above.
|
||||
"thresholds.cpu_warn": 80, "thresholds.cpu_crit": 90,
|
||||
"thresholds.mem_warn": 80, "thresholds.mem_crit": 90,
|
||||
"thresholds.disk_warn": 80, "thresholds.disk_crit": 90,
|
||||
"thresholds.load_warn": 80, "thresholds.load_crit": 100,
|
||||
"thresholds.temp_warn": 70, "thresholds.temp_crit": 85,
|
||||
"thresholds.uptime_warn": 99.0, "thresholds.uptime_crit": 95.0,
|
||||
"plugins.index_url": "https://git.fabledsword.com/bvandeusen/Steward-plugins/raw/branch/main/index.yaml",
|
||||
# Default-enabled plugins. These are the generic, non-vendor-specific
|
||||
# bundled plugins (protocols/standards, not a single product) — useful on
|
||||
@@ -224,6 +234,53 @@ def to_ldap_cfg(settings: dict[str, Any]) -> dict:
|
||||
return {k[len("ldap."):]: settings.get(k, DEFAULTS[k]) for k in DEFAULTS if k.startswith("ldap.")}
|
||||
|
||||
|
||||
def to_thresholds_cfg(settings: dict[str, Any]) -> dict:
|
||||
"""Per-metric (warn, crit, direction) policy for degraded-value coloring.
|
||||
|
||||
Centralizes "what counts as degraded" so templates just name a metric kind
|
||||
via the threshold_style() jinja global. `dir` is "high" (higher is worse,
|
||||
e.g. CPU) or "low" (lower is worse, e.g. uptime %). Latency reuses the
|
||||
existing ping good/warn thresholds.
|
||||
"""
|
||||
g = settings.get
|
||||
return {
|
||||
"cpu": {"warn": g("thresholds.cpu_warn", 80), "crit": g("thresholds.cpu_crit", 90), "dir": "high"},
|
||||
"mem": {"warn": g("thresholds.mem_warn", 80), "crit": g("thresholds.mem_crit", 90), "dir": "high"},
|
||||
"disk": {"warn": g("thresholds.disk_warn", 80), "crit": g("thresholds.disk_crit", 90), "dir": "high"},
|
||||
"load": {"warn": g("thresholds.load_warn", 80), "crit": g("thresholds.load_crit", 100), "dir": "high"},
|
||||
"temp": {"warn": g("thresholds.temp_warn", 70), "crit": g("thresholds.temp_crit", 85), "dir": "high"},
|
||||
"latency": {"warn": g("ping.threshold.good_ms", 50), "crit": g("ping.threshold.warn_ms", 200), "dir": "high"},
|
||||
"uptime": {"warn": g("thresholds.uptime_warn", 99.0), "crit": g("thresholds.uptime_crit", 95.0), "dir": "low"},
|
||||
}
|
||||
|
||||
|
||||
def threshold_style_for(value: Any, kind: str, thresholds: dict) -> str:
|
||||
"""Return an inline-style fragment (amber at warn, red at crit) for a metric.
|
||||
|
||||
The Python twin of the old _macros.metric_style, but reading configurable
|
||||
cutoffs from `thresholds` (see to_thresholds_cfg) and handling both
|
||||
directions. Empty string when normal/unknown/None — drop straight into a
|
||||
span's style="".
|
||||
"""
|
||||
if value is None:
|
||||
return ""
|
||||
th = thresholds.get(kind)
|
||||
if not th:
|
||||
return ""
|
||||
warn, crit, direction = th["warn"], th["crit"], th.get("dir", "high")
|
||||
if direction == "low":
|
||||
if value < crit:
|
||||
return "color:var(--red);font-weight:700;"
|
||||
if value < warn:
|
||||
return "color:var(--yellow);font-weight:600;"
|
||||
else:
|
||||
if value >= crit:
|
||||
return "color:var(--red);font-weight:700;"
|
||||
if value >= warn:
|
||||
return "color:var(--yellow);font-weight:600;"
|
||||
return ""
|
||||
|
||||
|
||||
def to_plugins_cfg(settings: dict[str, Any]) -> dict:
|
||||
"""Assemble {plugin_name: {...config}} from all plugin.* keys."""
|
||||
result = {}
|
||||
|
||||
Reference in New Issue
Block a user