import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Progress } from "@/components/ui/progress"; import React, { useEffect, useState } from "react"; import { DockerCpuChart } from "./docker-cpu-chart"; import { DockerMemoryChart } from "./docker-memory-chart"; import { DockerBlockChart } from "./docker-block-chart"; import { DockerNetworkChart } from "./docker-network-chart"; import { DockerDiskChart } from "./docker-disk-chart"; import { api } from "@/utils/api"; interface Props { appName: string; } export interface DockerStats { cpu: { value: number; time: string; }; memory: { value: { used: number; free: number; usedPercentage: number; total: number; }; time: string; }; block: { value: { readMb: number; writeMb: number; }; time: string; }; network: { value: { inputMb: number; outputMb: number; }; time: string; }; disk: { value: { diskTotal: number; diskUsage: number; diskUsedPercentage: number; diskFree: number; }; time: string; }; } export type DockerStatsJSON = { cpu: DockerStats["cpu"][]; memory: DockerStats["memory"][]; block: DockerStats["block"][]; network: DockerStats["network"][]; disk: DockerStats["disk"][]; }; export const DockerMonitoring = ({ appName }: Props) => { const { data } = api.application.readAppMonitoring.useQuery( { appName }, { refetchOnWindowFocus: false, }, ); const [acummulativeData, setAcummulativeData] = useState({ cpu: [], memory: [], block: [], network: [], disk: [], }); const [currentData, setCurrentData] = useState({ cpu: { value: 0, time: "", }, memory: { value: { used: 0, free: 0, usedPercentage: 0, total: 0, }, time: "", }, block: { value: { readMb: 0, writeMb: 0, }, time: "", }, network: { value: { inputMb: 0, outputMb: 0, }, time: "", }, disk: { value: { diskTotal: 0, diskUsage: 0, diskUsedPercentage: 0, diskFree: 0 }, time: "", }, }); useEffect(() => { if (!data) return; setCurrentData({ cpu: data.cpu[data.cpu.length - 1] ?? currentData.cpu, memory: data.memory[data.memory.length - 1] ?? currentData.memory, block: data.block[data.block.length - 1] ?? currentData.block, network: data.network[data.network.length - 1] ?? currentData.network, disk: data.disk[data.disk.length - 1] ?? currentData.disk, }); setAcummulativeData(data); }, [data]); useEffect(() => { const protocol = window.location.protocol === "https:" ? "wss:" : "ws:"; const wsUrl = `${protocol}//${window.location.host}/listen-docker-stats-monitoring?appName=${appName}`; const ws = new WebSocket(wsUrl); ws.onmessage = (e) => { const value = JSON.parse(e.data); if (!value) return; const data = { cpu: value.data.cpu ?? currentData.cpu, memory: value.data.memory ?? currentData.memory, block: value.data.block ?? currentData.block, disk: value.data.disk ?? currentData.disk, network: value.data.network ?? currentData.network, }; setCurrentData(data); setAcummulativeData((prevData) => ({ cpu: [...prevData.cpu, data.cpu], memory: [...prevData.memory, data.memory], block: [...prevData.block, data.block], network: [...prevData.network, data.network], disk: [...prevData.disk, data.disk], })); }; ws.onclose = (e) => { console.log(e.reason); }; return () => ws.close(); }, [appName]); return (
Monitoring Watch the usage of your server in the current app
CPU Used: {currentData.cpu.value.toFixed(2)}%
Memory {`Used: ${(currentData.memory.value.used / 1024).toFixed( 2, )} GB / Limit: ${( currentData.memory.value.total / 1024 ).toFixed(2)} GB`}
{appName === "dokploy" && (
Space {`Used: ${currentData.disk.value.diskUsage} GB / Limit: ${currentData.disk.value.diskTotal} GB`}
)}
Block I/O {`Used: ${currentData.block.value.readMb.toFixed( 2, )} MB / Limit: ${currentData.block.value.writeMb.toFixed( 3, )} MB`}
Network {`In MB: ${currentData.network.value.inputMb.toFixed( 2, )} MB / Out MB: ${currentData.network.value.outputMb.toFixed( 2, )} MB`}
); };