diff --git a/agent/pve.go b/agent/pve.go index 07bd11d5..1a4d069c 100644 --- a/agent/pve.go +++ b/agent/pve.go @@ -82,14 +82,18 @@ func (pm *pveManager) getPVEStats() ([]*container.PveNodeStats, error) { var sent_delta, recv_delta float64 if initialized { secondsElapsed := time.Since(resourceStats.PrevReadTime).Seconds() - sent_delta = float64(total_sent-resourceStats.PrevNet.Sent) / secondsElapsed - recv_delta = float64(total_recv-resourceStats.PrevNet.Recv) / secondsElapsed + if secondsElapsed > 0 { + sent_delta = float64(total_sent-resourceStats.PrevNet.Sent) / secondsElapsed + recv_delta = float64(total_recv-resourceStats.PrevNet.Recv) / secondsElapsed + } } + resourceStats.PrevNet.Sent = total_sent + resourceStats.PrevNet.Recv = total_recv resourceStats.PrevReadTime = time.Now() // Update final stats values resourceStats.Cpu = twoDecimals(100.0 * resource.CPU * float64(resource.MaxCPU) / float64(pm.cpuCount)) - resourceStats.Mem = float64(resource.Mem) + resourceStats.Mem = bytesToMegabytes(float64(resource.Mem)) resourceStats.Bandwidth = [2]uint64{uint64(sent_delta), uint64(recv_delta)} stats = append(stats, resourceStats) diff --git a/internal/site/src/components/charts/container-chart.tsx b/internal/site/src/components/charts/container-chart.tsx index f9274e1f..058fd1e2 100644 --- a/internal/site/src/components/charts/container-chart.tsx +++ b/internal/site/src/components/charts/container-chart.tsx @@ -23,14 +23,16 @@ export default memo(function ContainerChart({ chartType, chartConfig, unit = "%", + filterStore = $containerFilter, }: { dataKey: string chartData: ChartData chartType: ChartType chartConfig: ChartConfig unit?: string + filterStore?: typeof $containerFilter }) { - const filter = useStore($containerFilter) + const filter = useStore(filterStore) const userSettings = useStore($userSettings) const { yAxisWidth, updateYAxisWidth } = useYAxisWidth() diff --git a/internal/site/src/components/routes/system.tsx b/internal/site/src/components/routes/system.tsx index 7d2bab7b..5c00b8c5 100644 --- a/internal/site/src/components/routes/system.tsx +++ b/internal/site/src/components/routes/system.tsx @@ -25,6 +25,7 @@ import { $containerFilter, $direction, $maxValues, + $pveFilter, $systems, $temperatureFilter, $userSettings, @@ -160,6 +161,7 @@ export default memo(function SystemDetail({ id }: { id: string }) { const [system, setSystem] = useState({} as SystemRecord) const [systemStats, setSystemStats] = useState([] as SystemStatsRecord[]) const [containerData, setContainerData] = useState([] as ChartData["containerData"]) + const [pveData, setPveData] = useState([] as ChartData["containerData"]) const temperatureChartRef = useRef(null) const persistChartTime = useRef(false) const [bottomSpacing, setBottomSpacing] = useState(0) @@ -177,8 +179,10 @@ export default memo(function SystemDetail({ id }: { id: string }) { persistChartTime.current = false setSystemStats([]) setContainerData([]) + setPveData([]) setDetails({} as SystemDetailsRecord) $containerFilter.set("") + $pveFilter.set("") } }, [id]) @@ -277,6 +281,10 @@ export default memo(function SystemDetail({ id }: { id: string }) { // Share chart config computation for all container charts const containerChartConfigs = useContainerChartConfigs(containerData) + // PVE chart data and configs + const pveSyntheticChartData = useMemo(() => ({ ...chartData, containerData: pveData }), [chartData, pveData]) + const pveChartConfigs = useContainerChartConfigs(pveData) + // make container stats for charts const makeContainerData = useCallback((containers: ContainerStatsRecord[]) => { const containerData = [] as ChartData["containerData"] @@ -307,7 +315,8 @@ export default memo(function SystemDetail({ id }: { id: string }) { Promise.allSettled([ getStats("system_stats", system, chartTime), getStats("container_stats", system, chartTime), - ]).then(([systemStats, containerStats]) => { + getStats("pve_stats", system, chartTime), + ]).then(([systemStats, containerStats, pveStats]) => { // loading: false setChartLoading(false) @@ -334,6 +343,17 @@ export default memo(function SystemDetail({ id }: { id: string }) { cache.set(cs_cache_key, containerData) } setContainerData(makeContainerData(containerData)) + // make new pve stats + const ps_cache_key = `${system.id}_${chartTime}_pve_stats` + let pveRecords = (cache.get(ps_cache_key) || []) as ContainerStatsRecord[] + if (pveStats.status === "fulfilled" && pveStats.value.length) { + pveRecords = pveRecords.concat(addEmptyValues(pveRecords, pveStats.value, expectedInterval)) + if (pveRecords.length > 120) { + pveRecords = pveRecords.slice(-100) + } + cache.set(ps_cache_key, pveRecords) + } + setPveData(makeContainerData(pveRecords)) }) }, [system, chartTime]) @@ -399,6 +419,7 @@ export default memo(function SystemDetail({ id }: { id: string }) { const showMax = maxValues && isLongerChart const containerFilterBar = containerData.length ? : null + const pveFilterBar = pveData.length ? : null const dataEmpty = !chartLoading && chartData.systemStats.length === 0 const lastGpus = systemStats.at(-1)?.stats?.g @@ -493,6 +514,24 @@ export default memo(function SystemDetail({ id }: { id: string }) { )} + {pveFilterBar && ( + + + + )} + )} + {pveFilterBar && ( + + + + )} + @@ -641,6 +698,24 @@ export default memo(function SystemDetail({ id }: { id: string }) { )} + {pveFilterBar && pveData.length > 0 && ( + + + + )} + {/* Swap chart */} {(systemStats.at(-1)?.stats.su ?? 0) > 0 && ( $chartTime.set(chart /** Container chart filter */ export const $containerFilter = atom("") +/** PVE chart filter */ +export const $pveFilter = atom("") + /** Temperature chart filter */ export const $temperatureFilter = atom("")