import { $servers, pb } from '@/lib/stores' import { ContainerStatsRecord, SystemRecord, SystemStatsRecord } from '@/types' import { Suspense, lazy, useEffect, useState } from 'react' import { Card, CardHeader, CardTitle, CardDescription, CardContent } from '../ui/card' import { useStore } from '@nanostores/react' import Spinner from '../spinner' // import CpuChart from '../charts/cpu-chart' // import MemChart from '../charts/mem-chart' // import DiskChart from '../charts/disk-chart' // import ContainerCpuChart from '../charts/container-cpu-chart' // import ContainerMemChart from '../charts/container-mem-chart' import { CpuIcon, MemoryStickIcon } from 'lucide-react' const CpuChart = lazy(() => import('../charts/cpu-chart')) 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')) function timestampToBrowserTime(timestamp: string) { const date = new Date(timestamp) return date.toLocaleString() } // function addColors(objects: Record[]) { // objects.forEach((obj, index) => { // const hue = ((index * 360) / objects.length) % 360 // Distribute hues evenly // obj.fill = `hsl(${hue}, 100%, 50%)` // Set fill to HSL color with full saturation and 50% lightness // }) // } export default function ServerDetail({ name }: { name: string }) { const servers = useStore($servers) const [server, setServer] = useState({} as SystemRecord) const [containers, setContainers] = useState([] as ContainerStatsRecord[]) const [serverStats, setServerStats] = useState([] as SystemStatsRecord[]) const [cpuChartData, setCpuChartData] = useState([] as { time: string; cpu: number }[]) const [memChartData, setMemChartData] = useState( [] as { time: string; mem: number; memUsed: number; memCache: number }[] ) const [diskChartData, setDiskChartData] = useState( [] as { time: string; disk: number; diskUsed: number }[] ) const [containerCpuChartData, setContainerCpuChartData] = useState( [] as Record[] ) const [containerMemChartData, setContainerMemChartData] = useState( [] as Record[] ) useEffect(() => { document.title = `${name} / Qoma` return () => { setContainerCpuChartData([]) setCpuChartData([]) setMemChartData([]) setDiskChartData([]) } }, [name]) // get stats useEffect(() => { if (!('name' in server)) { return } pb.collection('system_stats') .getList(1, 60, { filter: `system="${server.id}"`, fields: 'created,stats', sort: '-created', }) .then((records) => { // console.log('sctats', records) setServerStats(records.items) }) }, [server, servers]) // get cpu data useEffect(() => { if (!serverStats.length) { return } // 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 }[] for (let { created, stats } of serverStats) { cpuData.push({ time: created, cpu: stats.c }) // 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 }) } setCpuChartData(cpuData.reverse()) setMemChartData(memData.reverse()) setDiskChartData(diskData.reverse()) }, [serverStats]) useEffect(() => { if ($servers.get().length === 0) { // console.log('skipping') return } // console.log('running') const matchingServer = servers.find((s) => s.name === name) as SystemRecord // console.log('found server', matchingServer) setServer(matchingServer) pb.collection('container_stats') .getList(1, 60, { filter: `system="${matchingServer.id}"`, fields: 'created,stats', sort: '-created', }) .then((records) => { // console.log('records', records) setContainers(records.items) }) }, [servers, name]) // container stats for charts useEffect(() => { // console.log('containers', containers) const containerCpuData = [] as Record[] const containerMemData = [] as Record[] for (let { created, stats } of containers) { let cpuData = { time: created } as Record let memData = { time: created } as Record for (let container of stats) { cpuData[container.n] = container.c memData[container.n] = container.m } containerCpuData.push(cpuData) containerMemData.push(memData) } setContainerCpuChartData(containerCpuData.reverse()) setContainerMemChartData(containerMemData.reverse()) }, [containers]) return ( <>

{name}

Total CPU Usage System-wide CPU utilization of the preceding one minute as a percentage }> {containerCpuChartData.length > 0 && ( Docker CPU Usage {' '} CPU utilization of docker containers }> )} Total Memory Usage Precise utilization at the recorded time }> {containerMemChartData.length > 0 && ( Docker Memory Usage {' '} Memory usage of docker containers }> {server?.stats?.m && } )} Disk Usage Precise usage at the recorded time }>
{server.name} {server.ip} - last updated: {timestampToBrowserTime(server.updated)}
{JSON.stringify(server, null, 2)}
{/* Containers
{JSON.stringify(containers, null, 2)}
*/} ) }