29 lines
1.2 KiB
Python
29 lines
1.2 KiB
Python
|
|
"""Tests for the file-based audit/heartbeat logging (core/audit.py)."""
|
||
|
|
import json
|
||
|
|
|
||
|
|
from core import audit
|
||
|
|
|
||
|
|
|
||
|
|
def test_log_heartbeat_writes_a_queryable_record(tmp_path, monkeypatch):
|
||
|
|
# The observability stack (Alloy → Loki) tails these JSONL files and lifts
|
||
|
|
# `level`/`tag` into labels, so a heartbeat must carry exactly those fields for
|
||
|
|
# the dashboard to query notifier liveness as {job="app-json", tag="heartbeat"}.
|
||
|
|
monkeypatch.setattr(audit, "HEARTBEAT_DIR", str(tmp_path))
|
||
|
|
audit.log_heartbeat("subscription-notifier", 900)
|
||
|
|
|
||
|
|
files = list(tmp_path.glob("heartbeat-*.jsonl"))
|
||
|
|
assert len(files) == 1
|
||
|
|
rec = json.loads(files[0].read_text().strip())
|
||
|
|
assert rec["tag"] == "heartbeat"
|
||
|
|
assert rec["level"] == "info"
|
||
|
|
assert rec["daemon"] == "subscription-notifier"
|
||
|
|
assert rec["interval_s"] == 900
|
||
|
|
assert "ts" in rec
|
||
|
|
|
||
|
|
|
||
|
|
def test_log_heartbeat_never_raises(monkeypatch):
|
||
|
|
# Best-effort, like the rest of audit: an unwritable dir must not bubble up into
|
||
|
|
# the notifier loop (which is why the loop can rely on calling it unguarded).
|
||
|
|
monkeypatch.setattr(audit, "HEARTBEAT_DIR", "/proc/nonexistent/cannot-write")
|
||
|
|
audit.log_heartbeat("subscription-notifier", 900) # no exception
|