feat(hosts): the live strip shows the hottest sensor's temperature, get_host marks sensors that don't count, and the Monitors card's button reads "Add" (#6803)
- The host page's live strip gains a Temperature tile: temp_c_max (real thermometers only), its last 6 h and the sensor setting it, graded by Settings → Thresholds and counted in the header's worst reading, in °C. - MCP get_host: each temperature carries `counted`; an unwired input is `counted: false` with `not_counted_because`, listed after the real ones. host_agent registers the judge (judge_sensors), so core imports no plugin. - The Monitors card's "Add monitor" wrapped into two lines beside the uptime; it reads "Add", titled "Add a monitor for this host". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -25,16 +25,16 @@ def test_worst_reading(readings, worst):
|
||||
assert worst_reading(readings, TH) == worst
|
||||
|
||||
|
||||
async def _vitals(app, *, cpu=40.0, mem=50.0, stale=False, seen_min=1):
|
||||
async def _vitals(app, *, cpu=40.0, mem=50.0, stale=False, seen_min=1, temp=None, hottest=None):
|
||||
readings = (("CPU", cpu, "cpu"), ("Memory", mem, "mem"), ("Disk /", 30.0, "disk"),
|
||||
("Load per core", 20, "load"))
|
||||
("Load per core", 20, "load"), ("Temperature", temp, "temp"))
|
||||
async with app.test_request_context("/plugins/host_agent/vitals/h1"):
|
||||
page = await render_plugin_template(
|
||||
app, "host_agent", "_host_vitals.html", reporting=True, stale=stale,
|
||||
reg=SimpleNamespace(host_id="h1", agent_version="1.9.0",
|
||||
last_seen_at=datetime.now(timezone.utc) - timedelta(minutes=seen_min)),
|
||||
cpu=cpu, mem=mem, disk_root=30.0, load_per_core=20,
|
||||
sparks={"cpu": "", "mem": "", "disk": "", "load": ""},
|
||||
cpu=cpu, mem=mem, disk_root=30.0, load_per_core=20, temp=temp, hottest=hottest,
|
||||
sparks={"cpu": "", "mem": "", "disk": "", "load": "", "temp": "<svg></svg>"},
|
||||
psi={"cpu": None, "mem": None, "io": None}, worst=worst_reading(readings, TH))
|
||||
return re.sub(r">\s+<", "><", " ".join(page.split()))
|
||||
|
||||
@@ -59,6 +59,22 @@ async def test_the_strip_at_the_top_of_the_page_leads_to_the_full_metrics(app):
|
||||
assert 'href="/plugins/host_agent/h1/"' in await _vitals(app)
|
||||
|
||||
|
||||
async def test_the_strip_shows_the_hottest_sensor_with_its_name_and_line(app):
|
||||
page = await _vitals(app, temp=62.0, hottest="Package id 0")
|
||||
assert "--tiles:5;" in page
|
||||
assert ('class="stat-tile stat-ok"><span class="stat-tile-label">Temperature</span>'
|
||||
'<span class="stat-tile-value">62°C</span>') in page
|
||||
assert '<svg></svg><span class="stat-tile-sensor" title="Package id 0">Package id 0</span>' in page
|
||||
without = await _vitals(app)
|
||||
assert "--tiles:4;" in without and ">Temperature<" not in without
|
||||
|
||||
|
||||
async def test_a_host_past_its_heat_threshold_says_so_in_degrees(app):
|
||||
page = await _vitals(app, temp=88.0, hottest="Package id 0") # crit at 85
|
||||
assert '<span class="tone-crit">Temperature 88°C</span> is past its critical threshold.' in page
|
||||
assert 'class="stat-tile stat-crit"><span class="stat-tile-label">Temperature</span>' in page
|
||||
|
||||
|
||||
async def test_a_stale_host_says_since_when_before_any_reading(app):
|
||||
page = await _vitals(app, mem=93.0, stale=True, seen_min=20)
|
||||
assert '<span class="badge badge-warn">Stale</span>' in page
|
||||
|
||||
Reference in New Issue
Block a user