From 4f3796e9bcee615f9341ce8009ea1283ece39ae5 Mon Sep 17 00:00:00 2001 From: Henry Dollman Date: Tue, 16 Jul 2024 16:40:37 -0400 Subject: [PATCH] update charts to use fixed time for x axis --- .../components/charts/container-cpu-chart.tsx | 22 ++++-- .../components/charts/container-mem-chart.tsx | 20 ++++-- site/src/components/charts/cpu-chart.tsx | 22 ++++-- site/src/components/charts/disk-chart.tsx | 24 +++++-- site/src/components/charts/mem-chart.tsx | 26 ++++--- site/src/components/routes/server.tsx | 67 ++++++++++++------- site/src/lib/utils.ts | 19 +++++- 7 files changed, 141 insertions(+), 59 deletions(-) diff --git a/site/src/components/charts/container-cpu-chart.tsx b/site/src/components/charts/container-cpu-chart.tsx index 57e14a1..cc082a6 100644 --- a/site/src/components/charts/container-cpu-chart.tsx +++ b/site/src/components/charts/container-cpu-chart.tsx @@ -8,10 +8,14 @@ import { ChartTooltipContent, } from '@/components/ui/chart' import { useMemo } from 'react' -import { formatShortDate, formatShortTime } from '@/lib/utils' +import { calculateXaxisTicks, formatShortDate, formatShortTime } from '@/lib/utils' import Spinner from '../spinner' -export default function ({ chartData }: { chartData: Record[] }) { +export default function ContainerCpuChart({ + chartData, +}: { + chartData: Record[] +}) { const chartConfig = useMemo(() => { let config = {} as Record< string, @@ -47,6 +51,8 @@ export default function ({ chartData }: { chartData: Record calculateXaxisTicks(chartData), [chartData]) + if (!chartData.length) { return } @@ -64,7 +70,7 @@ export default function ({ chartData }: { chartData: Record Math.max(Math.ceil(max), 0.4)]} - // tickCount={5} + width={47} tickLine={false} axisLine={false} unit={'%'} @@ -72,6 +78,10 @@ export default function ({ chartData }: { chartData: Record formatShortDate(data[0].payload.time)} // @ts-ignore itemSorter={(a, b) => b.value - a.value} content={} diff --git a/site/src/components/charts/container-mem-chart.tsx b/site/src/components/charts/container-mem-chart.tsx index ede30f8..fe91a67 100644 --- a/site/src/components/charts/container-mem-chart.tsx +++ b/site/src/components/charts/container-mem-chart.tsx @@ -8,10 +8,14 @@ import { ChartTooltipContent, } from '@/components/ui/chart' import { useMemo } from 'react' -import { formatShortDate, formatShortTime } from '@/lib/utils' +import { calculateXaxisTicks, formatShortDate, formatShortTime } from '@/lib/utils' import Spinner from '../spinner' export default function ({ chartData }: { chartData: Record[] }) { + if (!chartData.length) { + return + } + const chartConfig = useMemo(() => { let config = {} as Record< string, @@ -47,9 +51,7 @@ export default function ({ chartData }: { chartData: Record - } + const ticks = useMemo(() => calculateXaxisTicks(chartData), [chartData]) return ( @@ -78,6 +80,10 @@ export default function ({ chartData }: { chartData: Record formatShortDate(data[0].payload.time)} // @ts-ignore itemSorter={(a, b) => b.value - a.value} content={} diff --git a/site/src/components/charts/cpu-chart.tsx b/site/src/components/charts/cpu-chart.tsx index ca92893..3850cbf 100644 --- a/site/src/components/charts/cpu-chart.tsx +++ b/site/src/components/charts/cpu-chart.tsx @@ -6,8 +6,9 @@ import { ChartTooltip, ChartTooltipContent, } from '@/components/ui/chart' -import { formatShortDate, formatShortTime } from '@/lib/utils' +import { calculateXaxisTicks, formatShortDate, formatShortTime } from '@/lib/utils' import Spinner from '../spinner' +import { useMemo } from 'react' const chartConfig = { cpu: { @@ -16,11 +17,13 @@ const chartConfig = { }, } satisfies ChartConfig -export default function CpuChart({ chartData }: { chartData: { time: string; cpu: number }[] }) { +export default function CpuChart({ chartData }: { chartData: { time: number; cpu: number }[] }) { if (!chartData?.length) { return } + const ticks = useMemo(() => calculateXaxisTicks(chartData), [chartData]) + return ( @@ -35,15 +38,24 @@ export default function CpuChart({ chartData }: { chartData: { time: string; cpu {/* todo: short time if first date is same day, otherwise short date */} + formatShortDate(data[0].payload.time)} + indicator="line" + /> } /> + } + const diskSize = useMemo(() => { return Math.round(chartData[0]?.disk) }, [chartData]) + const ticks = useMemo(() => calculateXaxisTicks(chartData), [chartData]) + // const ticks = useMemo(() => { // let ticks = [0] // for (let i = 1; i < diskSize; i += diskSize / 5) { @@ -38,10 +44,6 @@ export default function DiskChart({ // return ticks // }, [diskSize]) - if (!chartData.length) { - return - } - return ( + formatShortDate(data[0].payload.time)} + indicator="line" + /> } /> + } + + const ticks = useMemo(() => calculateXaxisTicks(chartData), [chartData]) + const totalMem = useMemo(() => { return Math.ceil(chartData[0]?.mem) }, [chartData]) @@ -33,10 +39,6 @@ export default function ({ [] ) satisfies ChartConfig - if (!chartData.length) { - return - } - return ( a.name.localeCompare(b.name)} - labelFormatter={formatShortDate} + labelFormatter={(_, data) => formatShortDate(data[0].payload.time)} indicator="line" /> } diff --git a/site/src/components/routes/server.tsx b/site/src/components/routes/server.tsx index 73f491c..1988bd8 100644 --- a/site/src/components/routes/server.tsx +++ b/site/src/components/routes/server.tsx @@ -27,22 +27,34 @@ export default function ServerDetail({ name }: { name: string }) { const [containers, setContainers] = useState([] as ContainerStatsRecord[]) const [serverStats, setServerStats] = useState([] as SystemStatsRecord[]) - const [cpuChartData, setCpuChartData] = useState([] as { time: string; cpu: number }[]) + const [cpuChartData, setCpuChartData] = useState([] as { time: number; cpu: number }[]) const [memChartData, setMemChartData] = useState( - [] as { time: string; mem: number; memUsed: number; memCache: number }[] + [] as { time: number; mem: number; memUsed: number; memCache: number }[] ) const [diskChartData, setDiskChartData] = useState( - [] as { time: string; disk: number; diskUsed: number }[] + [] as { time: number; disk: number; diskUsed: number }[] ) - const [containerCpuChartData, setContainerCpuChartData] = useState( + const [dockerCpuChartData, setDockerCpuChartData] = useState( [] as Record[] ) - const [containerMemChartData, setContainerMemChartData] = useState( + const [dockerMemChartData, setDockerMemChartData] = useState( [] as Record[] ) useEffect(() => { document.title = `${name} / Beszel` + return () => { + console.log('unmounting') + setServer({} as SystemRecord) + setCpuChartData([]) + setMemChartData([]) + setDiskChartData([]) + setDockerCpuChartData([]) + setDockerMemChartData([]) + } + }, [name]) + + useEffect(() => { if (server?.id && server.name === name) { return } @@ -97,14 +109,19 @@ export default function ServerDetail({ name }: { name: string }) { console.log('stats', serverStats) // let maxCpu = 0 - const cpuData = [] as { time: string; cpu: number }[] - const memData = [] as { time: string; mem: number; memUsed: number; memCache: number }[] - const diskData = [] as { time: string; disk: number; diskUsed: number }[] + const cpuData = [] as typeof cpuChartData + const memData = [] as typeof memChartData + const diskData = [] as typeof diskChartData for (let { created, stats } of serverStats) { - cpuData.push({ time: created, cpu: stats.cpu }) - // maxCpu = Math.max(maxCpu, stats.c) - memData.push({ time: created, mem: stats.m, memUsed: stats.mu, memCache: stats.mb }) - diskData.push({ time: created, disk: stats.d, diskUsed: stats.du }) + const time = new Date(created).getTime() + cpuData.push({ time, cpu: stats.cpu }) + memData.push({ + time, + mem: stats.m, + memUsed: stats.mu, + memCache: stats.mb, + }) + diskData.push({ time, disk: stats.d, diskUsed: stats.du }) } setCpuChartData(cpuData.reverse()) setMemChartData(memData.reverse()) @@ -119,7 +136,6 @@ export default function ServerDetail({ name }: { name: string }) { sort: '-created', }) .then((records) => { - // console.log('containers', records) setContainers(records) }) }, [server]) @@ -127,22 +143,23 @@ export default function ServerDetail({ name }: { name: string }) { // container stats for charts useEffect(() => { // console.log('containers', containers) - const containerCpuData = [] as Record[] - const containerMemData = [] as Record[] + const dockerCpuData = [] as Record[] + const dockerMemData = [] as Record[] for (let { created, stats } of containers) { - let cpuData = { time: created } as Record - let memData = { time: created } as Record + const time = new Date(created).getTime() + let cpuData = { time } as (typeof dockerCpuChartData)[0] + let memData = { time } as (typeof dockerMemChartData)[0] for (let container of stats) { cpuData[container.n] = container.c memData[container.n] = container.m } - containerCpuData.push(cpuData) - containerMemData.push(memData) + dockerCpuData.push(cpuData) + dockerMemData.push(memData) } // console.log('containerMemData', containerMemData) - setContainerCpuChartData(containerCpuData.reverse()) - setContainerMemChartData(containerMemData.reverse()) + setDockerCpuChartData(dockerCpuData.reverse()) + setDockerMemChartData(dockerMemData.reverse()) }, [containers]) const uptime = useMemo(() => { console.log('making uptime') @@ -206,18 +223,18 @@ export default function ServerDetail({ name }: { name: string }) { - {containerCpuChartData.length > 0 && ( + {dockerCpuChartData.length > 0 && ( - + )} - {containerMemChartData.length > 0 && ( + {dockerMemChartData.length > 0 && ( - + )} diff --git a/site/src/lib/utils.ts b/site/src/lib/utils.ts index dcf7b88..37f1a7d 100644 --- a/site/src/lib/utils.ts +++ b/site/src/lib/utils.ts @@ -50,7 +50,10 @@ const shortTimeFormatter = new Intl.DateTimeFormat(undefined, { hour: 'numeric', minute: 'numeric', }) -export const formatShortTime = (timestamp: string) => shortTimeFormatter.format(new Date(timestamp)) +export const formatShortTime = (timestamp: string) => { + // console.log('ts', timestamp) + return shortTimeFormatter.format(new Date(timestamp)) +} const shortDateFormatter = new Intl.DateTimeFormat(undefined, { day: 'numeric', @@ -60,7 +63,10 @@ const shortDateFormatter = new Intl.DateTimeFormat(undefined, { hour: 'numeric', minute: 'numeric', }) -export const formatShortDate = (timestamp: string) => shortDateFormatter.format(new Date(timestamp)) +export const formatShortDate = (timestamp: string) => { + console.log('ts', timestamp) + return shortDateFormatter.format(new Date(timestamp)) +} export const updateFavicon = (newIconUrl: string) => ((document.querySelector("link[rel='icon']") as HTMLLinkElement).href = newIconUrl) @@ -118,3 +124,12 @@ export function getPbTimestamp(timeString: string) { return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` } + +export const calculateXaxisTicks = (chartData: any[]) => { + const ticks: number[] = [] + const lastDate = chartData.at(-1)!.time + for (let i = 60; i >= 0; i--) { + ticks.push(lastDate - i * 60 * 1000) + } + return ticks +}