mirror of
https://github.com/henrygd/beszel.git
synced 2026-04-22 04:31:50 +02:00
updates
This commit is contained in:
@@ -97,15 +97,15 @@ export function getProbeColumns(longestName = 0, longestTarget = 0): ColumnDef<N
|
|||||||
{
|
{
|
||||||
id: "latency",
|
id: "latency",
|
||||||
accessorFn: (record) => record.latency,
|
accessorFn: (record) => record.latency,
|
||||||
// invertSorting: true,
|
invertSorting: true,
|
||||||
header: ({ column }) => <HeaderButton column={column} name={t`Latency`} Icon={ActivityIcon} />,
|
header: ({ column }) => <HeaderButton column={column} name={t`Latency`} Icon={ActivityIcon} />,
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const val = row.original.latency
|
const val = row.original.latency
|
||||||
if (val === undefined) {
|
if (!val) {
|
||||||
return <span className="ms-1.5 text-muted-foreground">-</span>
|
return <span className="ms-1.5 text-muted-foreground">-</span>
|
||||||
}
|
}
|
||||||
let color = "bg-green-500"
|
let color = "bg-green-500"
|
||||||
if (!val || val > 200) {
|
if (val > 200) {
|
||||||
color = "bg-yellow-500"
|
color = "bg-yellow-500"
|
||||||
}
|
}
|
||||||
if (val > 2000) {
|
if (val > 2000) {
|
||||||
@@ -125,18 +125,18 @@ export function getProbeColumns(longestName = 0, longestTarget = 0): ColumnDef<N
|
|||||||
invertSorting: true,
|
invertSorting: true,
|
||||||
header: ({ column }) => <HeaderButton column={column} name={t`Loss`} Icon={WifiOffIcon} />,
|
header: ({ column }) => <HeaderButton column={column} name={t`Loss`} Icon={WifiOffIcon} />,
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const val = row.original.loss
|
const { loss, latency } = row.original
|
||||||
if (val === undefined) {
|
if (loss === undefined || (!latency && !loss)) {
|
||||||
return <span className="ms-1.5 text-muted-foreground">-</span>
|
return <span className="ms-1.5 text-muted-foreground">-</span>
|
||||||
}
|
}
|
||||||
let color = "bg-green-500"
|
let color = "bg-green-500"
|
||||||
if (val > 0) {
|
if (loss) {
|
||||||
color = val > 20 ? "bg-red-500" : "bg-yellow-500"
|
color = loss > 20 ? "bg-red-500" : "bg-yellow-500"
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<span className="ms-1.5 tabular-nums flex gap-2 items-center">
|
<span className="ms-1.5 tabular-nums flex gap-2 items-center">
|
||||||
<span className={cn("shrink-0 size-2 rounded-full", color)} />
|
<span className={cn("shrink-0 size-2 rounded-full", color)} />
|
||||||
{val}%
|
{loss}%
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ export default function NetworkProbesTableNew({
|
|||||||
<Trans>Network Probes</Trans>
|
<Trans>Network Probes</Trans>
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<div className="text-sm text-muted-foreground flex items-center flex-wrap">
|
<div className="text-sm text-muted-foreground flex items-center flex-wrap">
|
||||||
<Trans>ICMP/TCP/HTTP latency monitoring from this agent</Trans>
|
<Trans>ICMP/TCP/HTTP latency monitoring from agents</Trans>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="md:ms-auto flex items-center gap-2">
|
<div className="md:ms-auto flex items-center gap-2">
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export function AddProbeDialog({ systemId }: { systemId?: string }) {
|
|||||||
const [protocol, setProtocol] = useState<string>("icmp")
|
const [protocol, setProtocol] = useState<string>("icmp")
|
||||||
const [target, setTarget] = useState("")
|
const [target, setTarget] = useState("")
|
||||||
const [port, setPort] = useState("")
|
const [port, setPort] = useState("")
|
||||||
const [probeInterval, setProbeInterval] = useState("60")
|
const [probeInterval, setProbeInterval] = useState("30")
|
||||||
const [name, setName] = useState("")
|
const [name, setName] = useState("")
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [selectedSystemId, setSelectedSystemId] = useState("")
|
const [selectedSystemId, setSelectedSystemId] = useState("")
|
||||||
@@ -37,7 +37,7 @@ export function AddProbeDialog({ systemId }: { systemId?: string }) {
|
|||||||
setProtocol("icmp")
|
setProtocol("icmp")
|
||||||
setTarget("")
|
setTarget("")
|
||||||
setPort("")
|
setPort("")
|
||||||
setProbeInterval("60")
|
setProbeInterval("30")
|
||||||
setName("")
|
setName("")
|
||||||
setSelectedSystemId("")
|
setSelectedSystemId("")
|
||||||
}
|
}
|
||||||
@@ -72,13 +72,13 @@ export function AddProbeDialog({ systemId }: { systemId?: string }) {
|
|||||||
<Trans>Add {{ foo: t`Probe` }}</Trans>
|
<Trans>Add {{ foo: t`Probe` }}</Trans>
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent>
|
<DialogContent className="max-w-md">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
<Trans>Add {{ foo: t`Network Probe` }}</Trans>
|
<Trans>Add {{ foo: t`Network Probe` }}</Trans>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
<Trans>Configure ICMP, TCP, or HTTP latency monitoring from this agent.</Trans>
|
<Trans>Configure latency monitoring from this agent.</Trans>
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<form onSubmit={handleSubmit} className="grid gap-4 tabular-nums">
|
<form onSubmit={handleSubmit} className="grid gap-4 tabular-nums">
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { RootDiskCharts, ExtraFsCharts } from "./system/charts/disk-charts"
|
|||||||
import { BandwidthChart, ContainerNetworkChart } from "./system/charts/network-charts"
|
import { BandwidthChart, ContainerNetworkChart } from "./system/charts/network-charts"
|
||||||
import { TemperatureChart, BatteryChart } from "./system/charts/sensor-charts"
|
import { TemperatureChart, BatteryChart } from "./system/charts/sensor-charts"
|
||||||
import { GpuPowerChart, GpuDetailCharts } from "./system/charts/gpu-charts"
|
import { GpuPowerChart, GpuDetailCharts } from "./system/charts/gpu-charts"
|
||||||
import { LazyContainersTable, LazySmartTable, LazySystemdTable, LazyNetworkProbesTableNew } from "./system/lazy-tables"
|
import { LazyContainersTable, LazySmartTable, LazySystemdTable, LazyNetworkProbesTable } from "./system/lazy-tables"
|
||||||
import { LoadAverageChart } from "./system/charts/load-average-chart"
|
import { LoadAverageChart } from "./system/charts/load-average-chart"
|
||||||
import { ContainerIcon, CpuIcon, HardDriveIcon, TerminalSquareIcon } from "lucide-react"
|
import { ContainerIcon, CpuIcon, HardDriveIcon, TerminalSquareIcon } from "lucide-react"
|
||||||
import { GpuIcon } from "../ui/icons"
|
import { GpuIcon } from "../ui/icons"
|
||||||
@@ -147,7 +147,7 @@ export default memo(function SystemDetail({ id }: { id: string }) {
|
|||||||
|
|
||||||
{hasSystemd && <LazySystemdTable systemId={system.id} />}
|
{hasSystemd && <LazySystemdTable systemId={system.id} />}
|
||||||
|
|
||||||
<LazyNetworkProbesTableNew systemId={system.id} systemData={systemData} />
|
<LazyNetworkProbesTable systemId={system.id} systemData={systemData} />
|
||||||
|
|
||||||
{/* <LazyNetworkProbesTable system={system} chartData={chartData} grid={grid} probeStats={probeStats} /> */}
|
{/* <LazyNetworkProbesTable system={system} chartData={chartData} grid={grid} probeStats={probeStats} /> */}
|
||||||
</>
|
</>
|
||||||
@@ -197,7 +197,7 @@ export default memo(function SystemDetail({ id }: { id: string }) {
|
|||||||
<SwapChart chartData={chartData} grid={grid} dataEmpty={dataEmpty} systemStats={systemStats} />
|
<SwapChart chartData={chartData} grid={grid} dataEmpty={dataEmpty} systemStats={systemStats} />
|
||||||
{pageBottomExtraMargin > 0 && <div style={{ marginBottom: pageBottomExtraMargin }}></div>}
|
{pageBottomExtraMargin > 0 && <div style={{ marginBottom: pageBottomExtraMargin }}></div>}
|
||||||
</div>
|
</div>
|
||||||
<LazyNetworkProbesTableNew systemId={system.id} systemData={systemData} />
|
<LazyNetworkProbesTable systemId={system.id} systemData={systemData} />
|
||||||
{/* <LazyNetworkProbesTable system={system} chartData={chartData} grid={grid} probeStats={probeStats} /> */}
|
{/* <LazyNetworkProbesTable system={system} chartData={chartData} grid={grid} probeStats={probeStats} /> */}
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import LineChartDefault, { DataPoint } from "@/components/charts/line-chart"
|
import LineChartDefault from "@/components/charts/line-chart"
|
||||||
import { pinnedAxisDomain } from "@/components/ui/chart"
|
import type { DataPoint } from "@/components/charts/line-chart"
|
||||||
import { toFixedFloat, decimalString } from "@/lib/utils"
|
import { toFixedFloat, decimalString } from "@/lib/utils"
|
||||||
import { useLingui } from "@lingui/react/macro"
|
import { useLingui } from "@lingui/react/macro"
|
||||||
import { ChartCard, FilterBar } from "../chart-card"
|
import { ChartCard, FilterBar } from "../chart-card"
|
||||||
@@ -31,33 +31,44 @@ export function LatencyChart({
|
|||||||
const { t } = useLingui()
|
const { t } = useLingui()
|
||||||
const filter = useStore($filter)
|
const filter = useStore($filter)
|
||||||
|
|
||||||
const dataPoints: DataPoint<NetworkProbeStatsRecord>[] = useMemo(() => {
|
const { dataPoints, visibleKeys } = useMemo(() => {
|
||||||
const count = probes.length
|
const count = probes.length
|
||||||
return probes
|
const points: DataPoint<NetworkProbeStatsRecord>[] = []
|
||||||
.sort((a, b) => a.name.localeCompare(b.name))
|
const visibleKeys: string[] = []
|
||||||
.map((p, i) => {
|
probes.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
const key = probeKey(p)
|
const filterTerms = filter
|
||||||
const filterTerms = filter
|
? filter
|
||||||
? filter
|
.toLowerCase()
|
||||||
.toLowerCase()
|
.split(" ")
|
||||||
.split(" ")
|
.filter((term) => term.length > 0)
|
||||||
.filter((term) => term.length > 0)
|
: []
|
||||||
: []
|
for (let i = 0; i < count; i++) {
|
||||||
const filtered = filterTerms.length > 0 && !filterTerms.some((term) => key.toLowerCase().includes(term))
|
const p = probes[i]
|
||||||
const strokeOpacity = filtered ? 0.1 : 1
|
const key = probeKey(p)
|
||||||
return {
|
const filtered = filterTerms.length > 0 && !filterTerms.some((term) => key.toLowerCase().includes(term))
|
||||||
label: p.name || p.target,
|
if (filtered) {
|
||||||
dataKey: (record: NetworkProbeStatsRecord) => record.stats?.[key]?.[0] ?? null,
|
continue
|
||||||
color: count <= 5 ? i + 1 : `hsl(${(i * 360) / count}, var(--chart-saturation), var(--chart-lightness))`,
|
}
|
||||||
strokeOpacity,
|
visibleKeys.push(key)
|
||||||
activeDot: !filtered,
|
points.push({
|
||||||
}
|
label: p.name || p.target,
|
||||||
|
dataKey: (record: NetworkProbeStatsRecord) => record.stats?.[key]?.[0] ?? "-",
|
||||||
|
color: count <= 5 ? i + 1 : `hsl(${(i * 360) / count}, var(--chart-saturation), var(--chart-lightness))`,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
return { dataPoints: points, visibleKeys }
|
||||||
}, [probes, filter])
|
}, [probes, filter])
|
||||||
|
|
||||||
|
const filteredProbeStats = useMemo(() => {
|
||||||
|
if (!visibleKeys.length) return probeStats
|
||||||
|
return probeStats.filter((record) => visibleKeys.some((key) => record.stats?.[key] != null))
|
||||||
|
}, [probeStats, visibleKeys])
|
||||||
|
|
||||||
|
const legend = dataPoints.length < 10
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChartCard
|
<ChartCard
|
||||||
legend
|
legend={legend}
|
||||||
cornerEl={<FilterBar store={$filter} />}
|
cornerEl={<FilterBar store={$filter} />}
|
||||||
empty={empty}
|
empty={empty}
|
||||||
title={t`Latency`}
|
title={t`Latency`}
|
||||||
@@ -66,13 +77,18 @@ export function LatencyChart({
|
|||||||
>
|
>
|
||||||
<LineChartDefault
|
<LineChartDefault
|
||||||
chartData={chartData}
|
chartData={chartData}
|
||||||
customData={probeStats}
|
customData={filteredProbeStats}
|
||||||
dataPoints={dataPoints}
|
dataPoints={dataPoints}
|
||||||
domain={pinnedAxisDomain()}
|
domain={["auto", "auto"]}
|
||||||
connectNulls
|
connectNulls
|
||||||
tickFormatter={(value) => `${toFixedFloat(value, value >= 10 ? 0 : 1)} ms`}
|
tickFormatter={(value) => `${toFixedFloat(value, value >= 10 ? 0 : 1)} ms`}
|
||||||
contentFormatter={({ value }) => `${decimalString(value, 2)} ms`}
|
contentFormatter={({ value }) => {
|
||||||
legend
|
if (value === "-") {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return `${decimalString(value, 2)} ms`
|
||||||
|
}}
|
||||||
|
legend={legend}
|
||||||
filter={filter}
|
filter={filter}
|
||||||
/>
|
/>
|
||||||
</ChartCard>
|
</ChartCard>
|
||||||
|
|||||||
@@ -42,11 +42,11 @@ export function LazySystemdTable({ systemId }: { systemId: string }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const NetworkProbesTableNew = lazy(() => import("@/components/network-probes-table/network-probes-table"))
|
const NetworkProbesTable = lazy(() => import("@/components/network-probes-table/network-probes-table"))
|
||||||
|
|
||||||
const cache = new Map<string, any>()
|
const cache = new Map<string, any>()
|
||||||
|
|
||||||
export function LazyNetworkProbesTableNew({ systemId, systemData }: { systemId: string; systemData: SystemData }) {
|
export function LazyNetworkProbesTable({ systemId, systemData }: { systemId: string; systemData: SystemData }) {
|
||||||
const { grid, chartData } = systemData ?? {}
|
const { grid, chartData } = systemData ?? {}
|
||||||
const [probes, setProbes] = useState<NetworkProbeRecord[]>([])
|
const [probes, setProbes] = useState<NetworkProbeRecord[]>([])
|
||||||
const chartTime = useStore($chartTime)
|
const chartTime = useStore($chartTime)
|
||||||
@@ -101,7 +101,7 @@ export function LazyNetworkProbesTableNew({ systemId, systemData }: { systemId:
|
|||||||
<div ref={ref} className={cn(isIntersecting && "contents")}>
|
<div ref={ref} className={cn(isIntersecting && "contents")}>
|
||||||
{isIntersecting && (
|
{isIntersecting && (
|
||||||
<>
|
<>
|
||||||
<NetworkProbesTableNew systemId={systemId} probes={probes} setProbes={setProbes} />
|
<NetworkProbesTable systemId={systemId} probes={probes} setProbes={setProbes} />
|
||||||
{!!chartData && (
|
{!!chartData && (
|
||||||
<LatencyChart
|
<LatencyChart
|
||||||
probeStats={probeStats}
|
probeStats={probeStats}
|
||||||
@@ -116,25 +116,3 @@ export function LazyNetworkProbesTableNew({ systemId, systemData }: { systemId:
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
const NetworkProbesTable = lazy(() => import("@/components/routes/system/network-probes"))
|
|
||||||
|
|
||||||
export function LazyNetworkProbesTable({
|
|
||||||
system,
|
|
||||||
chartData,
|
|
||||||
grid,
|
|
||||||
probeStats,
|
|
||||||
}: {
|
|
||||||
system: any
|
|
||||||
chartData: any
|
|
||||||
grid: any
|
|
||||||
probeStats: any
|
|
||||||
}) {
|
|
||||||
const { isIntersecting, ref } = useIntersectionObserver()
|
|
||||||
return (
|
|
||||||
<div ref={ref} className={cn(isIntersecting && "contents")}>
|
|
||||||
{isIntersecting && (
|
|
||||||
<NetworkProbesTable system={system} chartData={chartData} grid={grid} realtimeProbeStats={probeStats} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user