The host page's link to the full metrics sat in the Agent card, under the anomaly card and the vitals strip, and was missed. It now heads the vitals strip at the top of the page. The anomaly card on the host, monitor, container and Traefik pages listed every anomaly of the last 30 days with its review form, reviewed ones included, and took over the top of the page. It is now one line: how many wait for review, which are out of their normal now, and a Review button to Alerts → Anomalies narrowed to that resource (?source=&resource=), where a review returns. It is hidden when nothing waits and nothing is going on. The callers fetch up to 100 rows so the count isn't capped at 10 or 20. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
45 lines
3.2 KiB
HTML
45 lines
3.2 KiB
HTML
{# Host health header — live polled into the host hub: live or stale, the worst
|
|
reading against Settings → Thresholds, last seen, then CPU / memory / disk /
|
|
load tiles graded by the same cutoffs (`grades`; CPU, memory and load within
|
|
the host's own normal for the hour read healthy, and `usual` says so). Renders nothing until the agent
|
|
reports (the Agent panel below then shows provisioning). #}
|
|
{% from "_macros.html" import status_badge, stat_tile %}
|
|
{% macro pct(v) %}{{ '%.0f%%'|format(v) if v is not none else '—' }}{% endmacro %}
|
|
{% set grades = grades or {} %}
|
|
{% if reporting %}
|
|
<section class="card host-health" aria-label="Host health">
|
|
<div class="host-health-head">
|
|
{{ status_badge('stale' if stale else 'up', 'Stale' if stale else 'Live') }}
|
|
<span class="host-health-summary">
|
|
{%- if stale %}No report since {{ reg.last_seen_at|ago }}; the readings below are from then.
|
|
{%- elif worst %}<span class="tone-{{ worst[2] }}">{{ worst[0] }} {{ pct(worst[1]) }}</span> is past its {{ "critical" if worst[2] == "crit" else "warning" }} threshold.
|
|
{%- elif usual %}Every reading is within its thresholds or its usual level for this hour.
|
|
{%- else %}Every reading is within its thresholds.{% endif -%}
|
|
</span>
|
|
<span class="problem-detail">
|
|
{%- if not stale %}seen {{ reg.last_seen_at|ago }}{% endif %}
|
|
{%- if reg.agent_version %}{{ " · " if not stale }}agent v{{ reg.agent_version }}{% endif -%}
|
|
{%- if clock and clock[0] %} · <span{% if clock[1] in ('warn', 'crit') %} class="tone-{{ clock[1] }}" title="Further from Steward's clock than Settings → Thresholds allows: check what keeps this host's time in sync"{% endif %}>{{ clock[0] }}</span>{% endif -%}
|
|
</span>
|
|
{# Charts, every mount, interface, disk and temperature sensor. #}
|
|
<a href="/plugins/host_agent/{{ reg.host_id }}/" class="btn btn-sm btn-ghost" style="margin-left:auto;">Full metrics →</a>
|
|
</div>
|
|
<div class="stat-strip host-health-tiles" style="margin-bottom:0;">
|
|
{{ stat_tile("CPU", pct(cpu), state=(grades.cpu or [status_class(cpu, 'cpu')])[0], hint=sparks.cpu|safe) }}
|
|
{{ stat_tile("Memory", pct(mem), state=(grades.mem or [status_class(mem, 'mem')])[0], hint=sparks.mem|safe) }}
|
|
{%- set inodes_worse = inodes_root is defined and inodes_root is not none and (disk_root is none or inodes_root > disk_root) %}
|
|
{{ stat_tile("Disk /", pct(disk_root) ~ (" · inodes " ~ pct(inodes_root) if inodes_worse else ""),
|
|
state=(grades.disk or [status_class(disk_root, 'disk')])[0], hint=sparks.disk|safe) }}
|
|
{{ stat_tile("Load per core", pct(load_per_core), state=(grades.load or [status_class(load_per_core, 'load')])[0], hint=sparks.load|safe) }}
|
|
</div>
|
|
{% if usual and not stale %}
|
|
<p class="field-hint" style="margin-top:0.6rem;">{{ usual | join("; ") | capitalize }}.</p>
|
|
{% endif %}
|
|
{% if psi.cpu is not none or psi.mem is not none or psi.io is not none %}
|
|
<p class="field-hint" style="margin-top:0.6rem;" title="Pressure stall: the share of the last 10 s that tasks waited for the resource">
|
|
Pressure (10 s): cpu {{ pct(psi.cpu) }} · mem {{ pct(psi.mem) }} · io {{ pct(psi.io) }}
|
|
</p>
|
|
{% endif %}
|
|
</section>
|
|
{% endif %}
|