From 224f51da1ac00b37358395ec8d2f0559060d5f3d Mon Sep 17 00:00:00 2001 From: Henry Dollman Date: Fri, 19 Jul 2024 17:00:19 -0400 Subject: [PATCH] add bandwidth chart --- .../src/components/charts/bandwidth-chart.tsx | 98 +++++++++++++++++++ site/src/components/routes/server.tsx | 26 ++--- site/src/main.tsx | 9 +- site/src/types.d.ts | 6 +- types.go | 2 + 5 files changed, 122 insertions(+), 19 deletions(-) create mode 100644 site/src/components/charts/bandwidth-chart.tsx diff --git a/site/src/components/charts/bandwidth-chart.tsx b/site/src/components/charts/bandwidth-chart.tsx new file mode 100644 index 0000000..236ca1c --- /dev/null +++ b/site/src/components/charts/bandwidth-chart.tsx @@ -0,0 +1,98 @@ +import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts' + +import { + ChartConfig, + ChartContainer, + ChartTooltip, + ChartTooltipContent, +} from '@/components/ui/chart' +import { formatShortDate, hourWithMinutes } from '@/lib/utils' +import Spinner from '../spinner' + +const chartConfig = { + recv: { + label: 'Received', + color: 'hsl(var(--chart-2))', + }, + sent: { + label: 'Sent', + color: 'hsl(var(--chart-1))', + }, +} satisfies ChartConfig + +export default function BandwidthChart({ + chartData, + ticks, +}: { + chartData: { time: number; sent: number; recv: number }[] + ticks: number[] +}) { + if (!chartData.length || !ticks.length) { + return + } + + return ( + + + + + {/* todo: short time if first date is same day, otherwise short date */} + + formatShortDate(data[0].payload.time)} + indicator="line" + /> + } + /> + + + + + ) +} diff --git a/site/src/components/routes/server.tsx b/site/src/components/routes/server.tsx index 6a3d5fb..378429e 100644 --- a/site/src/components/routes/server.tsx +++ b/site/src/components/routes/server.tsx @@ -9,7 +9,6 @@ import ChartTimeSelect from '../charts/chart-time-select' import { chartTimeData, cn, getPbTimestamp } from '@/lib/utils' import { Separator } from '../ui/separator' import { scaleTime } from 'd3-scale' -import DiskIoChart from '../charts/disk-io-chart' import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip' const CpuChart = lazy(() => import('../charts/cpu-chart')) @@ -17,6 +16,8 @@ const ContainerCpuChart = lazy(() => import('../charts/container-cpu-chart')) const MemChart = lazy(() => import('../charts/mem-chart')) const ContainerMemChart = lazy(() => import('../charts/container-mem-chart')) const DiskChart = lazy(() => import('../charts/disk-chart')) +const DiskIoChart = lazy(() => import('../charts/disk-io-chart')) +const BandwidthChart = lazy(() => import('../charts/bandwidth-chart')) function timestampToBrowserTime(timestamp: string) { const date = new Date(timestamp) @@ -42,6 +43,9 @@ export default function ServerDetail({ name }: { name: string }) { const [diskIoChartData, setDiskIoChartData] = useState( [] as { time: number; read: number; write: number }[] ) + const [bandwidthChartData, setBandwidthChartData] = useState( + [] as { time: number; sent: number; recv: number }[] + ) const [dockerCpuChartData, setDockerCpuChartData] = useState( [] as Record[] ) @@ -56,6 +60,7 @@ export default function ServerDetail({ name }: { name: string }) { setCpuChartData([]) setMemChartData([]) setDiskChartData([]) + setBandwidthChartData([]) setDockerCpuChartData([]) setDockerMemChartData([]) } @@ -71,17 +76,6 @@ export default function ServerDetail({ name }: { name: string }) { } }, [name, server, servers]) - // if visiting directly, make sure server gets set when servers are loaded - // useEffect(() => { - // if (!('id' in server)) { - // const matchingServer = servers.find((s) => s.name === name) as SystemRecord - // if (matchingServer) { - // console.log('setting server') - // setServer(matchingServer) - // } - // } - // }, [servers]) - // get stats useEffect(() => { if (!server.id) { @@ -114,6 +108,7 @@ export default function ServerDetail({ name }: { name: string }) { const memData = [] as typeof memChartData const diskData = [] as typeof diskChartData const diskIoData = [] as typeof diskIoChartData + const networkData = [] as typeof bandwidthChartData for (let { created, stats } of serverStats) { const time = new Date(created).getTime() cpuData.push({ time, cpu: stats.cpu }) @@ -125,11 +120,13 @@ export default function ServerDetail({ name }: { name: string }) { }) diskData.push({ time, disk: stats.d, diskUsed: stats.du }) diskIoData.push({ time, read: stats.dr, write: stats.dw }) + networkData.push({ time, sent: stats.ns, recv: stats.nr }) } setCpuChartData(cpuData) setMemChartData(memData) setDiskChartData(diskData) setDiskIoChartData(diskIoData) + setBandwidthChartData(networkData) }, [serverStats]) useEffect(() => { @@ -278,6 +275,11 @@ export default function ServerDetail({ name }: { name: string }) { > + + + + + {server.name} diff --git a/site/src/main.tsx b/site/src/main.tsx index 2545647..3553e25 100644 --- a/site/src/main.tsx +++ b/site/src/main.tsx @@ -44,8 +44,9 @@ import { } from './components/ui/dropdown-menu.tsx' import { AlertRecord, SystemRecord } from './types' import { $router, Link, navigate } from './components/router.tsx' +import ServerDetail from './components/routes/server.tsx' -const ServerDetail = lazy(() => import('./components/routes/server.tsx')) +// const ServerDetail = lazy(() => import('./components/routes/server.tsx')) const CommandPalette = lazy(() => import('./components/command-palette.tsx')) const LoginPage = lazy(() => import('./components/login/login.tsx')) @@ -103,11 +104,7 @@ const App = () => { } else if (page.path === '/') { return } else if (page.route === 'server') { - return ( - - - - ) + return } } diff --git a/site/src/types.d.ts b/site/src/types.d.ts index 1b58a70..fe12558 100644 --- a/site/src/types.d.ts +++ b/site/src/types.d.ts @@ -48,6 +48,10 @@ export interface SystemStats { dr: number /** disk write (mb) */ dw: number + /** network sent (mb) */ + ns: number + /** network received (mb) */ + nr: number } export interface ContainerStatsRecord extends RecordModel { @@ -66,7 +70,7 @@ interface ContainerStats { export interface SystemStatsRecord extends RecordModel { system: string - info: SystemStats + stats: SystemStats } export interface AlertRecord extends RecordModel { diff --git a/types.go b/types.go index 0574ae5..9e59e7c 100644 --- a/types.go +++ b/types.go @@ -39,6 +39,8 @@ type SystemStats struct { DiskPct float64 `json:"dp"` DiskRead float64 `json:"dr"` DiskWrite float64 `json:"dw"` + NetworkSent float64 `json:"ns"` + NetworkRecv float64 `json:"nr"` } type ContainerStats struct {