diff --git a/apps/dokploy/components/dashboard/monitoring/free/container/docker-block-chart.tsx b/apps/dokploy/components/dashboard/monitoring/free/container/docker-block-chart.tsx index 91db49869..01989753a 100644 --- a/apps/dokploy/components/dashboard/monitoring/free/container/docker-block-chart.tsx +++ b/apps/dokploy/components/dashboard/monitoring/free/container/docker-block-chart.tsx @@ -1,3 +1,4 @@ +import { formatMb, toMb } from "@dokploy/server/monitoring/units"; import { format } from "date-fns"; import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"; import { @@ -29,8 +30,8 @@ export const DockerBlockChart = ({ accumulativeData }: Props) => { const transformedData = accumulativeData.map((item, index) => ({ time: item.time, name: `Point ${index + 1}`, - readMb: item.value.readMb, - writeMb: item.value.writeMb, + readMb: toMb(item.value.readMb), + writeMb: toMb(item.value.writeMb), })); return ( @@ -77,7 +78,7 @@ export const DockerBlockChart = ({ accumulativeData }: Props) => { }} formatter={(value, name) => { const label = name === "readMb" ? "Read" : "Write"; - return [`${value} MB`, label]; + return [formatMb(Number(value)), label]; }} /> } diff --git a/apps/dokploy/components/dashboard/monitoring/free/container/docker-network-chart.tsx b/apps/dokploy/components/dashboard/monitoring/free/container/docker-network-chart.tsx index 56e512d52..92f23e75b 100644 --- a/apps/dokploy/components/dashboard/monitoring/free/container/docker-network-chart.tsx +++ b/apps/dokploy/components/dashboard/monitoring/free/container/docker-network-chart.tsx @@ -1,3 +1,4 @@ +import { formatMb, toMb } from "@dokploy/server/monitoring/units"; import { format } from "date-fns"; import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"; import { @@ -29,8 +30,8 @@ export const DockerNetworkChart = ({ accumulativeData }: Props) => { const transformedData = accumulativeData.map((item, index) => ({ time: item.time, name: `Point ${index + 1}`, - inMB: item.value.inputMb, - outMB: item.value.outputMb, + inMB: toMb(item.value.inputMb), + outMB: toMb(item.value.outputMb), })); return ( @@ -73,7 +74,7 @@ export const DockerNetworkChart = ({ accumulativeData }: Props) => { }} formatter={(value, name) => { const label = name === "inMB" ? "In" : "Out"; - return [`${value} MB`, label]; + return [formatMb(Number(value)), label]; }} /> } diff --git a/apps/dokploy/components/dashboard/monitoring/free/container/show-free-container-monitoring.tsx b/apps/dokploy/components/dashboard/monitoring/free/container/show-free-container-monitoring.tsx index 782b19134..54b7bace4 100644 --- a/apps/dokploy/components/dashboard/monitoring/free/container/show-free-container-monitoring.tsx +++ b/apps/dokploy/components/dashboard/monitoring/free/container/show-free-container-monitoring.tsx @@ -1,3 +1,4 @@ +import { formatMb } from "@dokploy/server/monitoring/units"; import { useEffect, useState } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Progress } from "@/components/ui/progress"; @@ -305,7 +306,7 @@ export const ContainerFreeMonitoring = ({
- {`Read: ${currentData.block.value.readMb} / Write: ${currentData.block.value.writeMb} `} + {`Read: ${formatMb(currentData.block.value.readMb)} / Write: ${formatMb(currentData.block.value.writeMb)}`}
@@ -318,7 +319,7 @@ export const ContainerFreeMonitoring = ({
- {`In MB: ${currentData.network.value.inputMb} / Out MB: ${currentData.network.value.outputMb} `} + {`In: ${formatMb(currentData.network.value.inputMb)} / Out: ${formatMb(currentData.network.value.outputMb)}`}
diff --git a/packages/server/src/monitoring/units.ts b/packages/server/src/monitoring/units.ts new file mode 100644 index 000000000..880e8cdb8 --- /dev/null +++ b/packages/server/src/monitoring/units.ts @@ -0,0 +1,41 @@ +const IO_UNIT_FACTORS: Record = { + B: 1 / 1e6, + kB: 1e-3, + KB: 1e-3, + MB: 1, + GB: 1e3, + TB: 1e6, + KiB: 1024 / 1e6, + MiB: 1024 ** 2 / 1e6, + GiB: 1024 ** 3 / 1e6, + TiB: 1024 ** 4 / 1e6, +}; + +export const toMb = (value: number | string | undefined): number => { + if (typeof value === "number") { + return value; + } + if (!value) { + return 0; + } + const parsed = Number.parseFloat(value); + if (Number.isNaN(parsed)) { + return 0; + } + const unit = value.replace(/[0-9.\s]/g, ""); + return parsed * (IO_UNIT_FACTORS[unit] ?? 1); +}; + +export const parseIoToMb = (raw: string | undefined): number => + Number(toMb(raw).toFixed(6)); + +export const formatMb = (value: number | string | undefined): string => { + const mb = toMb(value); + if (mb >= 1000) { + return `${(mb / 1000).toFixed(2)} GB`; + } + if (mb < 0.01 && mb > 0) { + return `${(mb * 1000).toFixed(2)} kB`; + } + return `${mb.toFixed(2)} MB`; +}; diff --git a/packages/server/src/monitoring/utils.ts b/packages/server/src/monitoring/utils.ts index 2c42b99a6..c2eefc8ae 100644 --- a/packages/server/src/monitoring/utils.ts +++ b/packages/server/src/monitoring/utils.ts @@ -1,6 +1,7 @@ import { promises } from "node:fs"; import { OSUtils } from "node-os-utils"; import { paths } from "../constants"; +import { parseIoToMb } from "./units"; export interface Container { BlockIO: string; @@ -28,13 +29,13 @@ export const recordAdvancedStats = async ( }); await updateStatsFile(appName, "block", { - readMb: stats.BlockIO.split(" ")[0], - writeMb: stats.BlockIO.split(" ")[2], + readMb: parseIoToMb(stats.BlockIO.split(" ")[0]), + writeMb: parseIoToMb(stats.BlockIO.split(" ")[2]), }); await updateStatsFile(appName, "network", { - inputMb: stats.NetIO.split(" ")[0], - outputMb: stats.NetIO.split(" ")[2], + inputMb: parseIoToMb(stats.NetIO.split(" ")[0]), + outputMb: parseIoToMb(stats.NetIO.split(" ")[2]), }); if (appName === "dokploy") {