fix: preserve chart history across reconnects, show gaps for missing data
Only wipe real (non-RTT) plugin data on an actual client reboot (boot flag), not on every ordinary OVERDUE/DOWN -> UP recovery. A transient network blip no longer erases CPU/memory/etc. history. Also split the shared time-series chart into separate line/area segments wherever the gap between samples is much larger than the typical spacing, so missing data (host overdue, or history that simply hasn't accumulated across a drop) renders as a visual gap instead of an interpolated line. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEimzMv4Q5EjFg3hoiZ69T
This commit is contained in:
@@ -14,10 +14,12 @@ class _FakeTransport:
|
||||
self.sent.append((data, addr))
|
||||
|
||||
|
||||
def _htb(name, rtt=None, interval=0):
|
||||
def _htb(name, rtt=None, interval=0, boot=0):
|
||||
d = {"name": name, "interval": interval, "id": 0}
|
||||
if rtt is not None:
|
||||
d["rtt"] = rtt
|
||||
if boot:
|
||||
d["boot"] = boot
|
||||
return parse_message(dicttos("HTB", d))
|
||||
|
||||
|
||||
@@ -94,10 +96,11 @@ def test_request_update_fires_on_recovery_even_with_rtt_history():
|
||||
assert ack.get("request_update")
|
||||
|
||||
|
||||
def test_recovery_clears_real_plugin_data_but_preserves_rtt_history():
|
||||
"""Regression for Finding 2: host.plugin_data.clear() on recovery must
|
||||
wipe real client-collected plugin data while leaving rtt_* history
|
||||
samples intact.
|
||||
def test_ordinary_recovery_preserves_real_plugin_data_and_rtt_history():
|
||||
"""An ordinary reconnect (no boot flag) — e.g. OVERDUE->UP after a
|
||||
transient network blip — must NOT wipe already-collected real plugin
|
||||
data (e.g. cpu_monitor, os_info) or rtt_* history. Only an actual
|
||||
client reboot invalidates that data (see the boot-flag test below).
|
||||
"""
|
||||
hbdclass.Host.hosts.pop("rtt-hist-host5", None)
|
||||
transport = _FakeTransport()
|
||||
@@ -116,8 +119,35 @@ def test_recovery_clears_real_plugin_data_but_preserves_rtt_history():
|
||||
host.add_plugin_data("os_info", {"os": "linux"}, timestamp=time.time())
|
||||
assert "os_info" in host.plugin_data
|
||||
|
||||
# Recovery heartbeat.
|
||||
# Ordinary recovery heartbeat — no boot flag.
|
||||
handle_datagram(_htb("rtt-hist-host5", rtt=13.0), ("127.0.0.1", 50000), transport, ctx)
|
||||
|
||||
assert "os_info" in host.plugin_data
|
||||
assert len(host.plugin_data["rtt_ipv4"]) == 4
|
||||
|
||||
|
||||
def test_boot_recovery_clears_real_plugin_data_but_preserves_rtt_history():
|
||||
"""A recovery heartbeat carrying the boot flag (client process actually
|
||||
restarted) must still wipe stale real plugin data, while rtt_* history
|
||||
(still a valid measurement, unaffected by a client reboot) survives.
|
||||
"""
|
||||
hbdclass.Host.hosts.pop("rtt-hist-host6", None)
|
||||
transport = _FakeTransport()
|
||||
ctx = _base_ctx()
|
||||
|
||||
for rtt in (10.0, 11.0, 12.0):
|
||||
handle_datagram(_htb("rtt-hist-host6", rtt=rtt), ("127.0.0.1", 50000), transport, ctx)
|
||||
|
||||
host = hbdclass.Host.hosts["rtt-hist-host6"]
|
||||
assert len(host.plugin_data["rtt_ipv4"]) == 3
|
||||
|
||||
conn = host.connections["IPv4"]
|
||||
conn.state = hbdclass.Connection.DOWN
|
||||
host.add_plugin_data("os_info", {"os": "linux"}, timestamp=time.time())
|
||||
assert "os_info" in host.plugin_data
|
||||
|
||||
# Recovery heartbeat with boot=1 — client process actually restarted.
|
||||
handle_datagram(_htb("rtt-hist-host6", rtt=13.0, boot=1), ("127.0.0.1", 50000), transport, ctx)
|
||||
|
||||
assert "os_info" not in host.plugin_data
|
||||
assert len(host.plugin_data["rtt_ipv4"]) == 4
|
||||
|
||||
Reference in New Issue
Block a user