feat(hosts): true live vitals strip; agent panel becomes management-only
Realizes the chosen host-summary layout: a thin live vitals bar at the very top, separate from the agent management panel (no more duplicated CPU/MEM/DISK/LOAD). - New fragment _host_vitals.html + route /plugins/host_agent/vitals/<id>: compact CPU / Memory / Disk(/) / Load-per-core (threshold-coloured + sparkline) + Pressure + live/stale·version·last-seen. Polled every 15s; renders nothing until the agent reports. - The metric computation (latest snapshot + 6h sparkline query + load/core + PSI) moves from host_panel into host_vitals. host_panel slims to management only (reg/target/reporting/stale/ansible) and no longer queries metrics; panel.html drops the gauge row + pressure block, keeping status + lifecycle actions. - hosts/detail.html: vitals strip on top (full width, live), then a 2-col [Monitors | Agent] grid, Ansible full width below, docker fragment last. UI only. Templates parse; plugin-template parse test covers the new fragment. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016Jg27rgypiW2efULXJDtMC
This commit is contained in:
@@ -14,39 +14,8 @@
|
||||
</div>
|
||||
|
||||
{% if reporting %}
|
||||
{# ── Reporting: at-a-glance metrics (+ sparkline trend) + lifecycle ── #}
|
||||
{% set cpu = hostlvl.get('cpu_pct') %}
|
||||
{% set mem = hostlvl.get('mem_used_pct') %}
|
||||
{% set lbl = "font-size:0.72rem;color:var(--text-muted);text-transform:uppercase;" %}
|
||||
<div style="display:flex;gap:1.5rem;flex-wrap:wrap;margin-bottom:0.6rem;">
|
||||
<div title="Average CPU utilization across all cores">
|
||||
<div style="{{ lbl }}">CPU</div>
|
||||
<div style="font-weight:600;{{ threshold_style(cpu, 'cpu') }}">{{ '%.0f%%'|format(cpu) if cpu is not none else '—' }}</div>
|
||||
{{ sparks.cpu | safe }}</div>
|
||||
<div title="RAM in use (total minus available; cache/buffers count as free)">
|
||||
<div style="{{ lbl }}">Memory</div>
|
||||
<div style="font-weight:600;{{ threshold_style(mem, 'mem') }}">{{ '%.0f%%'|format(mem) if mem is not none else '—' }}</div>
|
||||
{{ sparks.mem | safe }}</div>
|
||||
<div title="Root filesystem (/) usage — see Full metrics for every mount">
|
||||
<div style="{{ lbl }}">Disk /</div>
|
||||
<div style="font-weight:600;{{ threshold_style(disk_root, 'disk') }}">{{ '%.0f%%'|format(disk_root) if disk_root is not none else '—' }}</div>
|
||||
{{ sparks.disk | safe }}</div>
|
||||
{# Load /core: 100% = run queue matches CPU capacity, so warn 80 / crit 100. #}
|
||||
<div title="1-minute load average ÷ {{ cores or '?' }} CPU cores (100% = run queue matches capacity). Raw 1m load: {{ '%.2f'|format(load1) if load1 is not none else '—' }}.">
|
||||
<div style="{{ lbl }}">Load /core</div>
|
||||
<div style="font-weight:600;{{ threshold_style(load_per_core, 'load') }}">{{ '%d%%'|format(load_per_core) if load_per_core is not none else ('%.2f'|format(load1) if load1 is not none else '—') }}</div>
|
||||
{{ sparks.load | safe }}</div>
|
||||
</div>
|
||||
{% if psi.cpu is not none or psi.mem is not none or psi.io is not none %}
|
||||
<div style="font-size:0.75rem;color:var(--text-muted);margin-bottom:0.9rem;"
|
||||
title="Pressure Stall Information — % of the last 10s that tasks were stalled waiting for the resource. Hardware-independent, comparable across hosts.">
|
||||
<span style="text-transform:uppercase;font-size:0.7rem;letter-spacing:0.04em;color:var(--text-dim);">Pressure 10s</span>
|
||||
CPU {{ '%.0f%%'|format(psi.cpu) if psi.cpu is not none else '—' }}
|
||||
· Mem {{ '%.0f%%'|format(psi.mem) if psi.mem is not none else '—' }}
|
||||
· IO {{ '%.0f%%'|format(psi.io) if psi.io is not none else '—' }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Reporting: live vitals are shown by the vitals strip above; this panel is
|
||||
lifecycle/management only. #}
|
||||
<div style="display:flex;gap:0.5rem;flex-wrap:wrap;align-items:center;">
|
||||
<a href="/plugins/host_agent/{{ host.id }}/" class="btn btn-sm btn-ghost">Full metrics →</a>
|
||||
{% if session.user_role == 'admin' %}
|
||||
|
||||
Reference in New Issue
Block a user