mirror of
https://github.com/henrygd/beszel.git
synced 2026-04-26 06:21:50 +02:00
update
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
import type { Column, ColumnDef } from "@tanstack/react-table"
|
||||
import type { CellContext, Column, ColumnDef } from "@tanstack/react-table"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { cn, decimalString, hourWithSeconds } from "@/lib/utils"
|
||||
import {
|
||||
GlobeIcon,
|
||||
TimerIcon,
|
||||
ActivityIcon,
|
||||
WifiOffIcon,
|
||||
Trash2Icon,
|
||||
ArrowLeftRightIcon,
|
||||
@@ -12,6 +11,7 @@ import {
|
||||
ServerIcon,
|
||||
ClockIcon,
|
||||
NetworkIcon,
|
||||
RefreshCwIcon,
|
||||
} from "lucide-react"
|
||||
import { t } from "@lingui/core/macro"
|
||||
import type { NetworkProbeRecord } from "@/types"
|
||||
@@ -61,7 +61,7 @@ export function getProbeColumns(longestName = 0, longestTarget = 0): ColumnDef<N
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`System`} Icon={ServerIcon} />,
|
||||
cell: ({ getValue }) => {
|
||||
const allSystems = useStore($allSystemsById)
|
||||
return <span className="ms-1.5 xl:w-34 block truncate">{allSystems[getValue() as string]?.name ?? ""}</span>
|
||||
return <span className="ms-1.5 xl:w-20 block truncate">{allSystems[getValue() as string]?.name ?? ""}</span>
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -91,33 +91,36 @@ export function getProbeColumns(longestName = 0, longestTarget = 0): ColumnDef<N
|
||||
{
|
||||
id: "interval",
|
||||
accessorFn: (record) => record.interval,
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`Interval`} Icon={TimerIcon} />,
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`Interval`} Icon={RefreshCwIcon} />,
|
||||
cell: ({ getValue }) => <span className="ms-1.5 tabular-nums">{getValue() as number}s</span>,
|
||||
},
|
||||
{
|
||||
id: "response",
|
||||
accessorFn: (record) => record.response,
|
||||
id: "res",
|
||||
accessorFn: (record) => record.res,
|
||||
invertSorting: true,
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`Response`} Icon={ActivityIcon} />,
|
||||
cell: ({ row }) => {
|
||||
const val = row.original.response
|
||||
if (!val) {
|
||||
return <span className="ms-1.5 text-muted-foreground">-</span>
|
||||
}
|
||||
let color = "bg-green-500"
|
||||
if (val > 200) {
|
||||
color = "bg-yellow-500"
|
||||
}
|
||||
if (val > 2000) {
|
||||
color = "bg-red-500"
|
||||
}
|
||||
return (
|
||||
<span className="ms-1.5 tabular-nums flex gap-2 items-center">
|
||||
<span className={cn("shrink-0 size-2 rounded-full", color)} />
|
||||
{decimalString(val, val < 100 ? 2 : 1).toLocaleString()} ms
|
||||
</span>
|
||||
)
|
||||
},
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`Response`} Icon={TimerIcon} />,
|
||||
cell: responseTimeCell,
|
||||
},
|
||||
{
|
||||
id: "res1h",
|
||||
accessorFn: (record) => record.resAvg1h,
|
||||
invertSorting: true,
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`Avg 1h`} Icon={TimerIcon} />,
|
||||
cell: responseTimeCell,
|
||||
},
|
||||
{
|
||||
id: "max1h",
|
||||
accessorFn: (record) => record.resMax1h,
|
||||
invertSorting: true,
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`Max 1h`} Icon={TimerIcon} />,
|
||||
cell: responseTimeCell,
|
||||
},
|
||||
{
|
||||
id: "min1h",
|
||||
accessorFn: (record) => record.resMin1h,
|
||||
invertSorting: true,
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`Min 1h`} Icon={TimerIcon} />,
|
||||
cell: responseTimeCell,
|
||||
},
|
||||
{
|
||||
id: "loss",
|
||||
@@ -125,8 +128,8 @@ export function getProbeColumns(longestName = 0, longestTarget = 0): ColumnDef<N
|
||||
invertSorting: true,
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`Loss`} Icon={WifiOffIcon} />,
|
||||
cell: ({ row }) => {
|
||||
const { loss, response } = row.original
|
||||
if (loss === undefined || (!response && !loss)) {
|
||||
const { loss, res } = row.original
|
||||
if (loss === undefined || (!res && !loss)) {
|
||||
return <span className="ms-1.5 text-muted-foreground">-</span>
|
||||
}
|
||||
let color = "bg-green-500"
|
||||
@@ -188,6 +191,25 @@ export function getProbeColumns(longestName = 0, longestTarget = 0): ColumnDef<N
|
||||
},
|
||||
]
|
||||
}
|
||||
function responseTimeCell(cell: CellContext<NetworkProbeRecord, unknown>) {
|
||||
const val = cell.getValue() as number | undefined
|
||||
if (!val) {
|
||||
return <span className="ms-1.5 text-muted-foreground">-</span>
|
||||
}
|
||||
let color = "bg-green-500"
|
||||
if (val > 200) {
|
||||
color = "bg-yellow-500"
|
||||
}
|
||||
if (val > 2000) {
|
||||
color = "bg-red-500"
|
||||
}
|
||||
return (
|
||||
<span className="ms-1.5 tabular-nums flex gap-2 items-center">
|
||||
<span className={cn("shrink-0 size-2 rounded-full", color)} />
|
||||
{decimalString(val, val < 100 ? 2 : 1).toLocaleString()}ms
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
function HeaderButton({
|
||||
column,
|
||||
|
||||
@@ -44,7 +44,7 @@ function ProbeChart({
|
||||
const filter = useStore($filter)
|
||||
|
||||
const { dataPoints, visibleKeys } = useMemo(() => {
|
||||
const sortedProbes = [...probes].sort((a, b) => b.response - a.response)
|
||||
const sortedProbes = [...probes].sort((a, b) => b.resAvg1h - a.resAvg1h)
|
||||
const count = sortedProbes.length
|
||||
const points: DataPoint<NetworkProbeStatsRecord>[] = []
|
||||
const visibleKeys: string[] = []
|
||||
@@ -115,7 +115,7 @@ export function ResponseChart({ probeStats, grid, probes, chartData, empty }: Pr
|
||||
empty={empty}
|
||||
valueIndex={0}
|
||||
title={t`Response`}
|
||||
description={t`Average round-trip time (ms)`}
|
||||
description={t`Average response time (ms)`}
|
||||
tickFormatter={(value) => `${toFixedFloat(value, value >= 10 ? 0 : 1)} ms`}
|
||||
contentFormatter={({ value }) => {
|
||||
if (typeof value !== "number") {
|
||||
@@ -137,7 +137,7 @@ export function LossChart({ probeStats, grid, probes, chartData, empty }: ProbeC
|
||||
probes={probes}
|
||||
chartData={chartData}
|
||||
empty={empty}
|
||||
valueIndex={3}
|
||||
valueIndex={4}
|
||||
title={t`Loss`}
|
||||
description={t`Packet loss (%)`}
|
||||
domain={[0, 100]}
|
||||
|
||||
@@ -32,7 +32,7 @@ function appendCacheValue(
|
||||
}
|
||||
|
||||
const NETWORK_PROBE_FIELDS =
|
||||
"id,name,system,target,protocol,port,interval,response,resMin1h,resMax1h,resAvg1h,loss,enabled,updated"
|
||||
"id,name,system,target,protocol,port,interval,res,resMin1h,resMax1h,resAvg1h,loss,enabled,updated"
|
||||
|
||||
interface UseNetworkProbesProps {
|
||||
systemId?: string
|
||||
@@ -254,7 +254,7 @@ function probesToStats(probes: NetworkProbeRecord[]): NetworkProbeStatsRecord["s
|
||||
const stats: NetworkProbeStatsRecord["stats"] = {}
|
||||
for (const probe of probes) {
|
||||
const key = probeKey(probe)
|
||||
stats[key] = [probe.response, 0, 0, probe.loss]
|
||||
stats[key] = [probe.res, probe.resAvg1h, probe.resMin1h, probe.resMax1h, probe.loss]
|
||||
}
|
||||
return stats
|
||||
}
|
||||
|
||||
2
internal/site/src/types.d.ts
vendored
2
internal/site/src/types.d.ts
vendored
@@ -552,7 +552,7 @@ export interface NetworkProbeRecord {
|
||||
target: string
|
||||
protocol: "icmp" | "tcp" | "http"
|
||||
port: number
|
||||
response: number
|
||||
res: number
|
||||
resMin1h: number
|
||||
resMax1h: number
|
||||
resAvg1h: number
|
||||
|
||||
Reference in New Issue
Block a user