This commit is contained in:
henrygd
2026-04-22 21:40:52 -04:00
parent 8f03cbf11c
commit 5fc774666f
12 changed files with 160 additions and 85 deletions

View File

@@ -124,22 +124,22 @@ export function getProbeColumns(longestName = 0, longestTarget = 0): ColumnDef<N
},
{
id: "loss",
accessorFn: (record) => record.loss,
accessorFn: (record) => record.loss1h,
invertSorting: true,
header: ({ column }) => <HeaderButton column={column} name={t`Loss`} Icon={WifiOffIcon} />,
header: ({ column }) => <HeaderButton column={column} name={t`Loss 1h`} Icon={WifiOffIcon} />,
cell: ({ row }) => {
const { loss, res } = row.original
if (loss === undefined || (!res && !loss)) {
const { loss1h, res } = row.original
if (loss1h === undefined || (!res && !loss1h)) {
return <span className="ms-1.5 text-muted-foreground">-</span>
}
let color = "bg-green-500"
if (loss) {
color = loss > 20 ? "bg-red-500" : "bg-yellow-500"
if (loss1h) {
color = loss1h > 20 ? "bg-red-500" : "bg-yellow-500"
}
return (
<span className="ms-1.5 tabular-nums flex gap-2 items-center">
<span className={cn("shrink-0 size-2 rounded-full", color)} />
{loss}%
{loss1h}%
</span>
)
},
@@ -232,7 +232,6 @@ function HeaderButton({
>
{Icon && <Icon className="size-4" />}
{name}
{/* <ArrowUpDownIcon className="size-4" /> */}
</Button>
)
}

View File

@@ -102,7 +102,7 @@ export default function NetworkProbesTableNew({
<Trans>Network Probes</Trans>
</CardTitle>
<div className="text-sm text-muted-foreground flex items-center flex-wrap">
<Trans>ICMP/TCP/HTTP response monitoring from agents</Trans>
<Trans>Response time monitoring from agents.</Trans>
</div>
</div>
<div className="md:ms-auto flex items-center gap-2">

View File

@@ -7,7 +7,6 @@ import type { ChartData, NetworkProbeRecord, NetworkProbeStatsRecord } from "@/t
import { useMemo } from "react"
import { atom } from "nanostores"
import { useStore } from "@nanostores/react"
import { probeKey } from "@/lib/use-network-probes"
const $filter = atom("")
@@ -47,7 +46,7 @@ function ProbeChart({
const sortedProbes = [...probes].sort((a, b) => b.resAvg1h - a.resAvg1h)
const count = sortedProbes.length
const points: DataPoint<NetworkProbeStatsRecord>[] = []
const visibleKeys: string[] = []
const visibleIDs: string[] = []
const filterTerms = filter
? filter
.toLowerCase()
@@ -56,25 +55,25 @@ function ProbeChart({
: []
for (let i = 0; i < count; i++) {
const p = sortedProbes[i]
const key = probeKey(p)
const filtered = filterTerms.length > 0 && !filterTerms.some((term) => key.toLowerCase().includes(term))
const label = p.name || p.target
const filtered = filterTerms.length > 0 && !filterTerms.some((term) => label.toLowerCase().includes(term))
if (filtered) {
continue
}
visibleKeys.push(key)
visibleIDs.push(p.id)
points.push({
order: i,
label: p.name || p.target,
dataKey: (record: NetworkProbeStatsRecord) => record.stats?.[key]?.[valueIndex] ?? "-",
label,
dataKey: (record: NetworkProbeStatsRecord) => record.stats?.[p.id]?.[valueIndex] ?? "-",
color: count <= 5 ? i + 1 : `hsl(${(i * 360) / count}, var(--chart-saturation), var(--chart-lightness))`,
})
}
return { dataPoints: points, visibleKeys }
return { dataPoints: points, visibleKeys: visibleIDs }
}, [probes, filter, valueIndex])
const filteredProbeStats = useMemo(() => {
if (!visibleKeys.length) return probeStats
return probeStats.filter((record) => visibleKeys.some((key) => record.stats?.[key] != null))
return probeStats.filter((record) => visibleKeys.some((id) => record.stats?.[id] != null))
}, [probeStats, visibleKeys])
const legend = dataPoints.length < 10

View File

@@ -32,7 +32,7 @@ function appendCacheValue(
}
const NETWORK_PROBE_FIELDS =
"id,name,system,target,protocol,port,interval,res,resMin1h,resMax1h,resAvg1h,loss,enabled,updated"
"id,name,system,target,protocol,port,interval,res,resMin1h,resMax1h,resAvg1h,loss1h,enabled,updated"
interface UseNetworkProbesProps {
systemId?: string
@@ -245,16 +245,10 @@ export function useNetworkProbesData(props: UseNetworkProbesProps) {
}
}
export function probeKey(p: NetworkProbeRecord) {
if (p.protocol === "tcp") return `${p.protocol}:${p.target}:${p.port}`
return `${p.protocol}:${p.target}`
}
function probesToStats(probes: NetworkProbeRecord[]): NetworkProbeStatsRecord["stats"] {
const stats: NetworkProbeStatsRecord["stats"] = {}
for (const probe of probes) {
const key = probeKey(probe)
stats[key] = [probe.res, probe.resAvg1h, probe.resMin1h, probe.resMax1h, probe.loss]
stats[probe.id] = [probe.res, probe.resAvg1h, probe.resMin1h, probe.resMax1h, probe.loss1h]
}
return stats
}

View File

@@ -556,7 +556,7 @@ export interface NetworkProbeRecord {
resMin1h: number
resMax1h: number
resAvg1h: number
loss: number
loss1h: number
interval: number
enabled: boolean
updated: string