import { getErrorMessage } from "@/lib/error-message.js"; import React from "react"; import { Activity, Cpu, HardDrive, Info, MemoryStick, Network, RefreshCw, } from "lucide-react"; import type { DockerStats } from "@/types"; import { getContainerStats } from "@/main-axios.ts"; import { useTranslation } from "react-i18next"; import { SectionCard } from "@/components/section-card"; import { DockerBadge } from "./ContainerCard.tsx"; import { useAdaptivePolling } from "@/hooks/use-adaptive-polling.ts"; interface ContainerStatsProps { sessionId: string; containerId: string; containerName: string; containerState: string; } export function ContainerStats({ sessionId, containerId, containerName, containerState, }: ContainerStatsProps): React.ReactElement { const { t } = useTranslation(); const [stats, setStats] = React.useState(null); const [isLoading, setIsLoading] = React.useState(false); const [error, setError] = React.useState(null); const statsRef = React.useRef(stats); statsRef.current = stats; const fetchStats = React.useCallback(async () => { if (containerState !== "running") return false; setIsLoading(true); setError(null); try { const data = await getContainerStats(sessionId, containerId); const previous = statsRef.current; const changed = !previous || Math.abs(parseFloat(data.cpu) - parseFloat(previous.cpu)) >= 1.5 || Math.abs( parseFloat(data.memoryPercent) - parseFloat(previous.memoryPercent), ) >= 1 || data.pids !== previous.pids; statsRef.current = data; setStats(data); return changed; } catch (err) { setError(getErrorMessage(err, t("docker.failedToFetchStats"))); } finally { setIsLoading(false); } }, [sessionId, containerId, containerState, t]); useAdaptivePolling( fetchStats, { minIntervalMs: 2_000, maxIntervalMs: 12_000, stablePollsPerStep: 2, maxRequestDutyCycle: 0.2, }, containerState === "running", ); if (containerState !== "running") { return (
{t("docker.containerNotRunning")} {t("docker.startContainerToViewStats")}
); } if (isLoading && !stats) { return (
{t("docker.loadingStats")}
); } if (error) { return (
{t("docker.errorLoadingStats")} {error}
); } if (!stats) { return (
{t("docker.noStatsAvailable")}
); } const cpuPercent = parseFloat(stats.cpu) || 0; const memPercent = parseFloat(stats.memoryPercent) || 0; return (
} >
{stats.cpu} {t("docker.current")}
} >
{stats.memoryPercent} {stats.memoryUsed} / {stats.memoryLimit}
} >
{t("docker.input")} {stats.netInput}
{t("docker.output")} {stats.netOutput}
} >
{t("docker.read")} {stats.blockRead}
{t("docker.write")} {stats.blockWrite}
{stats.pids && (
{t("docker.pids")} {stats.pids}
)}
} >
{t("docker.name")} {containerName}
{t("docker.id")} {containerId.substring(0, 12)}
{t("docker.state")}
); }