claire/tests/test_telemetry_event.py
Natalie bda5dad83d feat(@projects/@claire): add host telemetry migration and reporting
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-05-31 18:08:43 -06:00

66 lines
2 KiB
Python

"""HostTelemetryReported event + host_telemetry projection (migration 0011).
The Linux `claire agent` emits these; they sync to plum and surface in
fleet_load. The projection is one row per host, last-write-wins by hlc.
"""
from __future__ import annotations
from claire import events as ev
from claire.db import migrate, open_db
from claire.hlc import HLCGenerator
def _conn():
conn = open_db(":memory:")
migrate(conn)
return conn
def _sample(host: str, cpu: float) -> ev.HostTelemetryReported:
return ev.HostTelemetryReported(
host=host,
cpu_percent=cpu,
mem_used_bytes=8_000_000_000,
mem_total_bytes=16_000_000_000,
load_1=1.5,
load_5=1.2,
load_15=0.9,
disk_used_bytes=100_000_000_000,
disk_total_bytes=500_000_000_000,
)
def test_telemetry_projection_upserts() -> None:
conn = _conn()
gen = HLCGenerator("test-machine")
ev.append(conn, gen, _sample("apricot", 12.5))
row = conn.execute(
"SELECT host, cpu_percent FROM host_telemetry WHERE host = 'apricot'"
).fetchone()
assert row is not None
assert row["cpu_percent"] == 12.5
def test_telemetry_last_write_wins_one_row_per_host() -> None:
conn = _conn()
gen = HLCGenerator("test-machine")
ev.append(conn, gen, _sample("apricot", 10.0))
ev.append(conn, gen, _sample("apricot", 99.0))
rows = conn.execute(
"SELECT cpu_percent FROM host_telemetry WHERE host = 'apricot'"
).fetchall()
assert len(rows) == 1 # upsert, not append
assert rows[0]["cpu_percent"] == 99.0 # latest wins
def test_telemetry_survives_replay() -> None:
"""Projection rebuilds identically from the event log."""
conn = _conn()
gen = HLCGenerator("test-machine")
ev.append(conn, gen, _sample("black", 42.0))
ev.replay(conn)
row = conn.execute(
"SELECT cpu_percent FROM host_telemetry WHERE host = 'black'"
).fetchone()
assert row is not None and row["cpu_percent"] == 42.0