"use client"; import { Cpu, Database, MemoryStick, Server } from "lucide-react"; import { useAdminQuery } from "@/components/admin/use-query"; import type { SystemResponse } from "@/components/admin/types"; import { PageHeader, RefreshButton, Panel, DataTable, ErrorState, TableSkeleton, TileSkeleton, StatGrid, StatTile, KV, Pill, Mono, type Column } from "@/components/admin/primitives"; import { bytes, duration, int, ms, num } from "@/components/admin/format"; import { cn } from "@/lib/utils"; type Service = SystemResponse["services"][number]; type TableRow = SystemResponse["tables"][number] & { __max: number }; const serviceCols: Column[] = [ { key: "status", header: "Status", render: (s) => {s.status} }, { key: "name", header: "Service", render: (s) => {s.name} }, { key: "node", header: "Node", mono: true, render: (s) => {s.node} }, { key: "version", header: "Version", mono: true, render: (s) => v{s.version} }, { key: "uptime", header: "Uptime", align: "right", render: (s) => (s.uptimeSec === null ? — : duration(s.uptimeSec)) }, { key: "latency", header: "Latency", align: "right", render: (s) => (s.latencyMs < 0 ? unreachable : ms(s.latencyMs, 1)) }, ]; const tableCols: Column[] = [ { key: "table", header: "Table", mono: true, render: (t) => {t.table} }, { key: "rows", header: "Live rows", align: "right", render: (t) => int(t.rows) }, { key: "bytes", header: "Total size", align: "right", render: (t) => bytes(t.bytes) }, { key: "share", header: "", render: (t) => , }, ]; export default function AdminSystemPage() { const q = useAdminQuery("/api/admin/system", { refreshMs: 15_000 }); const d = q.data; const maxBytes = d ? Math.max(1, ...d.tables.map((t) => num(t.bytes))) : 1; const tables = (d?.tables ?? []).map((t) => ({ ...t, __max: maxBytes })); const down = d?.services.filter((s) => s.status !== "ok").length ?? 0; const memPct = d ? 1 - d.process.freeMemMb / Math.max(1, d.process.totalMemMb) : 0; return ( <> void q.refresh()} loading={q.refreshing} />} /> {q.error && !d ? ( void q.refresh()} /> ) : !d ? (
) : (
} /> {ms(d.spins.avg)} avg} sub={`p95 ${ms(d.spins.p95)} · n=${int(d.spins.n)}`} tone={num(d.spins.p95) > 250 ? "danger" : "neutral"} /> } /> l.toFixed(2)).join(" / ")} sub={`${d.process.cpus} CPUs · ${d.process.platform}`} tone={d.process.load[0] > d.process.cpus ? "danger" : "neutral"} icon={} /> s.name} dense />
l.toFixed(2)).join(" / "), mono: true }, { label: "Memory used", value: `${int(d.process.totalMemMb - d.process.freeMemMb)} / ${int(d.process.totalMemMb)} MB` }, { label: "RSS / heap", value: `${int(d.process.rssMb)} / ${int(d.process.heapMb)} MB` }, ]} />
Host memory {Math.round(memPct * 100)}%
0.9 ? "bg-danger" : memPct > 0.75 ? "bg-[#ffb454]" : "bg-accent")} style={{ width: `${Math.round(memPct * 100)}%` }} />
}> t.table} dense empty="No table statistics available." />
)} ); }