Masters / test_telemetry.py
Reooiq96's picture
Exact copy of Reoo88/On @ 826bfe0 (relay-v2.32-gap-filler)
f847423 verified
Raw History Blame Contribute Delete
5.44 kB
#!/usr/bin/env python3
"""Telemetry safety contract: append-only, fail-open, and control-path neutral.
No live services and no FFmpeg. The important production guarantee is not
that storage can never fail, but that telemetry can fail/drop its own records
without raising into, blocking, or steering a stream.
"""
import json
import os
import pathlib
import sys
import tempfile
import time
ROOT = pathlib.Path(__file__).resolve().parent
sys.path.insert(0, str(ROOT))
from telemetry import Telemetry, http_status_from_exception
passed = failed = 0
def check(name, condition, detail=""):
global passed, failed
if condition:
passed += 1
print("PASS %s" % name)
else:
failed += 1
print("FAIL %s %s" % (name, detail))
def wait_records(store, count, timeout=3.0):
deadline = time.time() + timeout
rows = []
while time.time() < deadline:
rows = store.read_records(100)
if len(rows) >= count:
return rows
time.sleep(0.02)
return rows
with tempfile.TemporaryDirectory() as tmp:
path = pathlib.Path(tmp) / "telemetry" / "telemetry.jsonl"
store = Telemetry(path)
key = store.start_session("alice", {
"mode": "copy",
"url": "https://signed.example/private?token=should-not-persist",
"nested": {"stream_key": "should-not-persist", "room_id": "123"},
})
check("session starts", bool(key))
check("observe accepts ffmpeg progress", store.observe(key, {
"ffmpeg_speed": 0.80, "ffmpeg_fps": 30.0, "source_bps": 900_000,
"output_seconds": 12.0,
}))
check("observe accepts recovered speed", store.observe(key, {
"ffmpeg_speed": 1.01, "ffmpeg_fps": 30.0, "source_bps": 2_400_000,
"output_seconds": 27.0,
}))
class Response:
status_code = 403
class HttpFailure(Exception):
response = Response()
check("http status extracted without message", http_status_from_exception(HttpFailure()) == 403)
check("source-open event accepted", store.event(key, "alice", "SOURCE_OPEN_ERROR", {
"stage": "initial_open", "error_type": "HTTPError", "http_status": 403,
"url": "https://signed.example/do-not-store",
}))
check("resolution event accepted", store.event(key, "alice", "RESOLUTION_CHANGE", {
"old_width": 720, "old_height": 1280, "new_width": 428, "new_height": 856,
}))
check("checkpoint accepted", store.checkpoint(key, "unit-test"))
check("finish accepted", store.finish(key, "unit finished", {"output_seconds": 27.0}))
rows = wait_records(store, 5)
kinds = [row.get("type") for row in rows]
check("writer persisted all record kinds", kinds == [
"session_start", "event", "event", "checkpoint", "session_finish"
], str(kinds))
raw = path.read_text(encoding="utf-8")
check("signed URL is not persisted", "signed.example" not in raw and "should-not-persist" not in raw)
finish = [row for row in rows if row.get("type") == "session_finish"][-1]
summary = finish["summary"]
check("summary identifies broadcaster", summary["broadcaster"] == "alice")
check("summary counts source-open status", summary["counters"].get("source_open_http_403") == 1,
str(summary["counters"]))
check("summary counts slow ffmpeg samples", summary["counters"].get("ffmpeg_speed_below_0_95_samples") == 1,
str(summary["counters"]))
check("summary averages ffmpeg speed", abs(summary["stats"]["ffmpeg_speed"]["avg"] - 0.905) < 0.0001,
str(summary["stats"].get("ffmpeg_speed")))
check("summary keeps minute buckets", len(summary["minutes"]) == 1, str(summary["minutes"]))
before = path.read_bytes()
reopened = Telemetry(path)
check("reopening telemetry does not truncate", path.read_bytes() == before)
check("reopened store reads old records", len(reopened.read_records(10)) == len(rows))
check("no delete/rotate/truncate API", not any(
hasattr(Telemetry, name) for name in ("delete", "rotate", "truncate", "clear", "purge")
))
os.environ["TELEMETRY_ENABLED"] = "0"
try:
disabled_path = pathlib.Path(tmp) / "disabled" / "telemetry.jsonl"
disabled = Telemetry(disabled_path)
check("disabled telemetry is a no-op", disabled.start_session("bob") is None and not disabled_path.exists())
finally:
os.environ.pop("TELEMETRY_ENABLED", None)
blocker = pathlib.Path(tmp) / "blocker"
blocker.write_text("not a directory", encoding="utf-8")
broken = Telemetry(blocker / "telemetry" / "telemetry.jsonl")
broken_key = broken.start_session("carol")
broken.observe(broken_key, {"ffmpeg_speed": 1.0})
broken.finish(broken_key, "storage unavailable")
deadline = time.time() + 3.0
while time.time() < deadline and broken.write_errors < 2:
time.sleep(0.02)
check("storage failure stays inside telemetry", broken.write_errors >= 2,
"write_errors=%s" % broken.write_errors)
relay_source = (ROOT / "relay.py").read_text(encoding="utf-8")
check("telemetry result is never a streaming condition", "if telemetry_" not in relay_source and
"while telemetry_" not in relay_source)
check("relay records HTTP status at initial open", "'stage':'initial_open'" in relay_source and
"http_status_from_exception" in relay_source)
print("\n%d passed, %d failed" % (passed, failed))
sys.exit(1 if failed else 0)