Add 5m and 10m load avg alerts and table values (#816)

Co-authored-by: henrygd <hank@henrygd.me>
This commit is contained in:
NeMeow
2025-07-12 19:47:06 -04:00
committed by henrygd
parent b5d55ead4a
commit 1ba362bafe
11 changed files with 139 additions and 40 deletions

View File

@@ -68,7 +68,7 @@ import { useStore } from "@nanostores/react"
import { cn, copyToClipboard, decimalString, isReadOnlyUser, useLocalStorage } from "@/lib/utils"
import AlertsButton from "../alerts/alert-button"
import { $router, Link, navigate } from "../router"
import { EthernetIcon, GpuIcon, ThermometerIcon } from "../ui/icons"
import { EthernetIcon, GpuIcon, HourglassIcon, ThermometerIcon } from "../ui/icons"
import { useLingui, Trans } from "@lingui/react/macro"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card"
import { Input } from "../ui/input"
@@ -83,8 +83,8 @@ function CellFormatter(info: CellContext<SystemRecord, unknown>) {
const val = (info.getValue() as number) || 0
return (
<div className="flex gap-2 items-center tabular-nums tracking-tight">
<span className="min-w-[3.3em]">{decimalString(val, 1)}%</span>
<span className="grow min-w-10 block bg-muted h-[1em] relative rounded-sm overflow-hidden">
<span className="min-w-8">{decimalString(val, 1)}%</span>
<span className="grow min-w-8 block bg-muted h-[1em] relative rounded-sm overflow-hidden">
<span
className={cn(
"absolute inset-0 w-full h-full origin-left",
@@ -144,7 +144,6 @@ export default function SystemsTable() {
}
return [
{
// size: 200,
size: 200,
minSize: 0,
accessorKey: "name",
@@ -163,6 +162,7 @@ export default function SystemsTable() {
return false
},
enableHiding: false,
invertSorting: false,
Icon: ServerIcon,
cell: (info) => (
<span className="flex gap-0.5 items-center text-base md:pe-5">
@@ -181,28 +181,26 @@ export default function SystemsTable() {
header: sortableHeader,
},
{
accessorKey: "info.cpu",
accessorFn: (originalRow) => originalRow.info.cpu,
id: "cpu",
name: () => t`CPU`,
invertSorting: true,
cell: CellFormatter,
Icon: CpuIcon,
header: sortableHeader,
},
{
accessorKey: "info.mp",
// accessorKey: "info.mp",
accessorFn: (originalRow) => originalRow.info.mp,
id: "memory",
name: () => t`Memory`,
invertSorting: true,
cell: CellFormatter,
Icon: MemoryStickIcon,
header: sortableHeader,
},
{
accessorKey: "info.dp",
accessorFn: (originalRow) => originalRow.info.dp,
id: "disk",
name: () => t`Disk`,
invertSorting: true,
cell: CellFormatter,
Icon: HardDriveIcon,
header: sortableHeader,
@@ -211,8 +209,6 @@ export default function SystemsTable() {
accessorFn: (originalRow) => originalRow.info.g,
id: "gpu",
name: () => "GPU",
invertSorting: true,
sortUndefined: -1,
cell: CellFormatter,
Icon: GpuIcon,
header: sortableHeader,
@@ -221,19 +217,50 @@ export default function SystemsTable() {
accessorFn: (originalRow) => originalRow.info.b || 0,
id: "net",
name: () => t`Net`,
invertSorting: true,
size: 50,
Icon: EthernetIcon,
header: sortableHeader,
cell(info) {
const val = info.getValue() as number
return <span className="tabular-nums whitespace-nowrap">{decimalString(val, val >= 100 ? 1 : 2)} MB/s</span>
},
},
{
accessorKey: "info.l5",
id: "l5",
name: () => t({ message: "L5", comment: "Load average 5 minutes" }),
size: 0,
hideSort: true,
Icon: HourglassIcon,
header: sortableHeader,
cell(info) {
const val = info.getValue() as number
if (!val) {
return null
}
return (
<span
className={cn("tabular-nums whitespace-nowrap", {
"ps-1": viewMode === "table",
})}
>
{decimalString(val, val >= 100 ? 1 : 2)} MB/s
<span className={cn("tabular-nums whitespace-nowrap", viewMode === "table" && "ps-1")}>
{decimalString(val)}
</span>
)
},
},
{
accessorKey: "info.l15",
id: "l15",
name: () => t({ message: "L15", comment: "Load average 15 minutes" }),
size: 0,
hideSort: true,
Icon: HourglassIcon,
header: sortableHeader,
cell(info) {
const val = info.getValue() as number
if (!val) {
return null
}
return (
<span className={cn("tabular-nums whitespace-nowrap", viewMode === "table" && "ps-1")}>
{decimalString(val)}
</span>
)
},
@@ -242,8 +269,6 @@ export default function SystemsTable() {
accessorFn: (originalRow) => originalRow.info.dt,
id: "temp",
name: () => t({ message: "Temp", comment: "Temperature label in systems table" }),
invertSorting: true,
sortUndefined: -1,
size: 50,
hideSort: true,
Icon: ThermometerIcon,
@@ -254,21 +279,17 @@ export default function SystemsTable() {
return null
}
return (
<span
className={cn("tabular-nums whitespace-nowrap", {
"ps-1.5": viewMode === "table",
})}
>
<span className={cn("tabular-nums whitespace-nowrap", viewMode === "table" && "ps-0.5")}>
{decimalString(val)} °C
</span>
)
},
},
{
accessorKey: "info.v",
accessorFn: (originalRow) => originalRow.info.v,
id: "agent",
name: () => t`Agent`,
invertSorting: true,
// invertSorting: true,
size: 50,
Icon: WifiIcon,
hideSort: true,
@@ -280,11 +301,7 @@ export default function SystemsTable() {
}
const system = info.row.original
return (
<span
className={cn("flex gap-2 items-center md:pe-5 tabular-nums", {
"ps-1": viewMode === "table",
})}
>
<span className={cn("flex gap-2 items-center md:pe-5 tabular-nums", viewMode === "table" && "ps-0.5")}>
<IndicatorDot
system={system}
className={
@@ -304,7 +321,7 @@ export default function SystemsTable() {
name: () => t({ message: "Actions", comment: "Table column" }),
size: 50,
cell: ({ row }) => (
<div className="flex justify-end items-center gap-1">
<div className="flex justify-end items-center gap-1 -ms-3">
<AlertsButton system={row.original} />
<ActionsButton system={row.original} />
</div>
@@ -328,6 +345,9 @@ export default function SystemsTable() {
columnVisibility,
},
defaultColumn: {
// sortDescFirst: true,
invertSorting: true,
sortUndefined: "last",
minSize: 0,
size: 900,
maxSize: 900,
@@ -511,7 +531,7 @@ function SystemsTableHead({ table, colLength }: { table: TableType<SystemRecord>
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead className="px-2" key={header.id}>
<TableHead className="px-1" key={header.id}>
{flexRender(header.column.columnDef.header, header.getContext())}
</TableHead>
)