G7.6: never let bookkeeping kill the monitor
An unwritable state path raised and took the whole canary down. That is the worst possible trade for a monitoring tool: it reports nothing at all, and reports it silently. State is an optimisation for transition detection; the probing is the point. Found by fat-fingering an env var, which is exactly how it would happen in production. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -601,3 +601,11 @@ def test_g35_did_not_disable_validation_to_register():
|
|||||||
one-time ordering problem."""
|
one-time ordering problem."""
|
||||||
for f in (ROOT / "scripts").glob("*.py"):
|
for f in (ROOT / "scripts").glob("*.py"):
|
||||||
assert "skip_validation" not in f.read_text()
|
assert "skip_validation" not in f.read_text()
|
||||||
|
|
||||||
|
|
||||||
|
def test_g76_canary_survives_an_unwritable_state_path():
|
||||||
|
"""A monitoring tool that dies of a config problem reports nothing at all,
|
||||||
|
and reports it silently. State is an optimisation; probing is the point."""
|
||||||
|
src = (ROOT / "scripts" / "canary.py").read_text()
|
||||||
|
save = src[src.index("def save_state") : src.index("def send_alert")]
|
||||||
|
assert "except OSError" in save
|
||||||
|
|||||||
@@ -156,8 +156,20 @@ def load_state() -> dict:
|
|||||||
|
|
||||||
|
|
||||||
def save_state(results: list[Result]) -> None:
|
def save_state(results: list[Result]) -> None:
|
||||||
|
"""Never let bookkeeping kill the monitor.
|
||||||
|
|
||||||
|
State is an optimisation — it lets the next run tell "still broken" from
|
||||||
|
"just broke". The probing is the valuable part. An unwritable path used to
|
||||||
|
raise here and take the whole canary down, which is the worst possible
|
||||||
|
trade: a monitoring tool that dies of a config problem reports nothing at
|
||||||
|
all, and reports it silently.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
with open(STATE_PATH, "w") as f:
|
with open(STATE_PATH, "w") as f:
|
||||||
json.dump({r.name: r.status for r in results}, f, indent=2)
|
json.dump({r.name: r.status for r in results}, f, indent=2)
|
||||||
|
except OSError as exc:
|
||||||
|
print(f"!! could not save state to {STATE_PATH}: {exc}")
|
||||||
|
print(" (probes still ran; transition detection is degraded this run)")
|
||||||
|
|
||||||
|
|
||||||
def send_alert(subject: str, lines: list[str]) -> bool:
|
def send_alert(subject: str, lines: list[str]) -> bool:
|
||||||
|
|||||||
Reference in New Issue
Block a user