Checklist: verify that sensor data reaches InfluxDB
New guided check "Sensor data in the database (InfluxDB)", also the last step of the Quick check on the green path. It queries InfluxDB (read token) for the newest point per measurement of the box and tells apart: sensor data arrives / status arrives without sensor data / offline now / never seen / check not possible. Polls every 30 s for up to 4 minutes. With a stopped RTC in the log it concludes that sensor readings are lost (stamped 1 Jan 2000): box A4:CB:8F:C9:47:3C sent only device_status and microphone. - service/influx.py: query, CSV parsing, classification (no new deps) - guides: new step type "influx" (host answers via influx_result) - Settings > InfluxDB access (or KOTA_INFLUX_TOKEN); token never logged - service status mapping for tech.influx.* findings Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2b6d43eb45
commit
66cb804102
11 files changed
+676
-15
No files matched your search
@@ -242,3 +242,95 @@ def test_skip_wait_and_report_contains_technician_checks(rig):
|
||||
assert runner.end.id == "update_slow"
|
||||
text = engine.report().to_text()
|
||||
assert "Technician checks:" in text and "Update is taking very long" in text
|
||||
|
||||
|
||||
# ------------------------------------------------------------ InfluxDB check
|
||||
RTC_STOPPED = [*BOOT, "I (2945) KOTA: rtc running=0 time=2000-01-01T00:00:00"]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def influx_rig(rig):
|
||||
engine, runner, clock, actions, board, log = rig
|
||||
return engine, runner, clock, actions, board
|
||||
|
||||
|
||||
def test_influx_ok_ends_healthy(influx_rig):
|
||||
engine, runner, clock, actions, board = influx_rig
|
||||
runner.start("influx")
|
||||
assert actions == ["influx"] and runner.view().waiting
|
||||
runner.influx_result("ok", "Sensor data arrives in InfluxDB", ["Device status: 1 min ago"])
|
||||
assert runner.end.id == "data_ok"
|
||||
assert any("InfluxDB: Sensor data arrives" in t for t in engine.technician)
|
||||
|
||||
|
||||
def test_influx_polls_until_sensors_arrive(influx_rig):
|
||||
engine, runner, clock, actions, board = influx_rig
|
||||
runner.start("influx")
|
||||
runner.influx_result("sensors_missing", "Status arrives, sensor data does not: SEN66")
|
||||
assert runner.end is None and "Checking again" in runner.view().note
|
||||
clock.t += 10
|
||||
runner.tick()
|
||||
assert actions == ["influx"] # not yet
|
||||
clock.t += 25
|
||||
runner.tick()
|
||||
assert actions == ["influx", "influx"] # polled again after poll_s
|
||||
runner.tick()
|
||||
assert actions == ["influx", "influx"] # no second query while one is pending
|
||||
runner.influx_result("ok", "Sensor data arrives in InfluxDB")
|
||||
assert runner.end.id == "data_ok"
|
||||
|
||||
|
||||
def test_influx_repeated_answer_is_noted_once(influx_rig):
|
||||
engine, runner, clock, actions, board = influx_rig
|
||||
runner.start("influx")
|
||||
for _ in range(3):
|
||||
runner.influx_result("silent", "No recent data in InfluxDB")
|
||||
clock.t += 31
|
||||
runner.tick()
|
||||
assert sum("InfluxDB:" in t for t in engine.technician) == 1
|
||||
|
||||
|
||||
def test_influx_sensors_missing_with_stopped_clock(influx_rig):
|
||||
engine, runner, clock, actions, board = influx_rig
|
||||
board(*RTC_STOPPED)
|
||||
runner.start("influx")
|
||||
runner.influx_result("sensors_missing", "Status arrives, sensor data does not")
|
||||
clock.t += 300 # past timeout_s
|
||||
runner.tick()
|
||||
assert runner.end.id == "sensors_clock"
|
||||
f = engine.findings["tech.influx.sensors_clock"]
|
||||
assert f.severity == Severity.ERROR and f.active
|
||||
|
||||
|
||||
def test_influx_sensors_missing_without_log_cause(influx_rig):
|
||||
engine, runner, clock, actions, board = influx_rig
|
||||
runner.start("influx")
|
||||
clock.t += 250
|
||||
runner.influx_result("sensors_missing", "Status arrives, sensor data does not")
|
||||
assert runner.end.id == "sensors_missing"
|
||||
|
||||
|
||||
def test_influx_unavailable_and_stale_results(rig):
|
||||
engine, runner, clock, actions, board, log = rig
|
||||
runner._on_action = lambda a: False # no token / host cannot query
|
||||
runner.start("influx")
|
||||
assert runner.end.id == "unavailable"
|
||||
runner.influx_result("ok", "late answer") # ignored: step already left
|
||||
assert runner.end.id == "unavailable"
|
||||
|
||||
|
||||
def test_influx_skip_uses_last_result(influx_rig):
|
||||
engine, runner, clock, actions, board = influx_rig
|
||||
runner.start("influx")
|
||||
runner.influx_result("silent", "No recent data in InfluxDB")
|
||||
runner.proceed()
|
||||
assert runner.end.id == "silent"
|
||||
|
||||
|
||||
def test_quick_check_green_ends_with_influx_check(influx_rig):
|
||||
engine, runner, clock, actions, board = influx_rig
|
||||
board(*BOOT)
|
||||
runner.start("quick")
|
||||
runner.answer("GREEN")
|
||||
runner.answer("0") # heartbeat blinking
|
||||
assert runner.guide.id == "influx" and actions == ["influx"]
|
||||
Reference in new issue
Block a user