Show memory and disk capacity (used/total) on dashboard tiles
Previously the Mem/Disk bars only showed a percentage. Plumbed the underlying byte totals through the whole stack -- collectors, DB (with a migration for the already-deployed CT122 instance), API, and the web tile -- so each card also shows e.g. "19.6/32.0 GB". Verified end-to-end with a throwaway local instance (seeded snapshot, logged in, screenshotted the rendered tile). Note: the SSH-collected hosts (omv, ripper) assume the remote monitor-readonly.sh script emits raw bytes for MEMLINE/DISK_, matching Proxmox's convention -- unverified since that script only lives on those two hosts, not in this repo. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,10 @@ export interface HostSummary {
|
||||
cpuPct: number | null;
|
||||
memPct: number | null;
|
||||
diskPct: number | null;
|
||||
memTotalBytes: number | null;
|
||||
memUsedBytes: number | null;
|
||||
diskTotalBytes: number | null;
|
||||
diskUsedBytes: number | null;
|
||||
memPressurePct: number | null;
|
||||
cpuPressurePct: number | null;
|
||||
uptimeSec: number | null;
|
||||
|
||||
@@ -15,6 +15,21 @@ function Bar({ label, pct }: { label: string; pct: number | null }) {
|
||||
);
|
||||
}
|
||||
|
||||
// Picks a unit off total capacity, applies it to both sides so "used/total"
|
||||
// reads as e.g. "12.3/32 GB" instead of mixing MB and GB.
|
||||
function formatCapacity(used: number | null, total: number | null): string | null {
|
||||
if (used === null || total === null || total <= 0) return null;
|
||||
const units: [number, string][] = [
|
||||
[1024 ** 4, "TB"],
|
||||
[1024 ** 3, "GB"],
|
||||
[1024 ** 2, "MB"],
|
||||
[1024, "KB"],
|
||||
];
|
||||
const [divisor, unit] = units.find(([d]) => total >= d) ?? [1, "B"];
|
||||
const fmt = (n: number) => (n / divisor >= 100 ? (n / divisor).toFixed(0) : (n / divisor).toFixed(1));
|
||||
return `${fmt(used)}/${fmt(total)} ${unit}`;
|
||||
}
|
||||
|
||||
function formatUptime(sec: number | null): string {
|
||||
if (sec === null) return "—";
|
||||
const days = Math.floor(sec / 86400);
|
||||
@@ -25,6 +40,9 @@ function formatUptime(sec: number | null): string {
|
||||
}
|
||||
|
||||
export function HostCard({ host }: { host: HostSummary }) {
|
||||
const memCapacity = formatCapacity(host.memUsedBytes, host.memTotalBytes);
|
||||
const diskCapacity = formatCapacity(host.diskUsedBytes, host.diskTotalBytes);
|
||||
|
||||
return (
|
||||
<div className={`host-card status-${host.status}`}>
|
||||
<div className="host-card-header">
|
||||
@@ -35,6 +53,12 @@ export function HostCard({ host }: { host: HostSummary }) {
|
||||
<Bar label="CPU" pct={host.cpuPct} />
|
||||
<Bar label="Mem" pct={host.memPct} />
|
||||
<Bar label="Disk" pct={host.diskPct} />
|
||||
{(memCapacity !== null || diskCapacity !== null) && (
|
||||
<div className="capacity-row">
|
||||
{memCapacity !== null && <span>Mem {memCapacity}</span>}
|
||||
{diskCapacity !== null && <span>Disk {diskCapacity}</span>}
|
||||
</div>
|
||||
)}
|
||||
<Sparkline history={host.history} />
|
||||
{(host.cpuPressurePct !== null || host.memPressurePct !== null) && (
|
||||
<div className="pressure-row">
|
||||
|
||||
@@ -181,6 +181,15 @@ body {
|
||||
margin-top: 0.35rem;
|
||||
}
|
||||
|
||||
.capacity-row {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
font-size: 0.7rem;
|
||||
color: #8b949e;
|
||||
margin-top: 0.15rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.device-count {
|
||||
color: #8b949e;
|
||||
font-weight: 400;
|
||||
|
||||
Reference in New Issue
Block a user