diff --git a/packages/integrations/src/beszel/beszel-types.ts b/packages/integrations/src/beszel/beszel-types.ts index 52643c701..e5c6566a5 100644 --- a/packages/integrations/src/beszel/beszel-types.ts +++ b/packages/integrations/src/beszel/beszel-types.ts @@ -94,8 +94,8 @@ export interface BeszelSystemDetails { * * Units: * - CPU/GPU/memory/disk percentages: 0–100 - * - Memory/disk absolute values (mu, du, etc.): bytes - * - Disk I/O (dr, dw): bytes/s + * - Memory/disk absolute values (mu, du, m, d, etc.): GB + * - Disk I/O (dr, dw): MB/s * - Network (ns, nr): bytes/s — all interfaces (including loopback, docker bridges) * - Bandwidth (b): bytes/s [sent, recv] — public interfaces only. Prefer b over ns/nr for user-facing charts */ @@ -110,35 +110,35 @@ export interface BeszelSystemStats { cpus?: number[]; /** load average [1m, 5m, 15m] */ la?: [number, number, number]; - /** total memory (bytes) */ + /** total memory (GB) */ m: number; - /** memory used (bytes) */ + /** memory used (GB) */ mu: number; /** memory usage (%) */ mp: number; - /** memory buffer/cache (bytes) */ + /** memory buffer/cache (GB) */ mb: number; - /** memory max used (bytes) */ + /** memory max used (GB) */ mm?: number; - /** memory zfs arc (bytes) */ + /** memory zfs arc (GB) */ mz?: number; - /** total swap (bytes) */ + /** total swap (GB) */ s: number; - /** swap used (bytes) */ + /** swap used (GB) */ su: number; - /** total disk (bytes) */ + /** total disk (GB) */ d: number; - /** disk used (bytes) */ + /** disk used (GB) */ du: number; /** disk usage (%) */ dp: number; - /** disk read (bytes/s) */ + /** disk read (MB/s) */ dr: number; - /** disk write (bytes/s) */ + /** disk write (MB/s) */ dw: number; - /** disk read max (bytes/s) */ + /** disk read max (MB/s) */ drm?: number; - /** disk write max (bytes/s) */ + /** disk write max (MB/s) */ dwm?: number; /** disk IOPS [read, write] */ dio?: [number, number]; @@ -236,13 +236,14 @@ export interface BeszelContainer { * One entry per container in a BeszelContainerStatsRecord. * * Network fields: b (bandwidth) is preferred when available; fall back to ns/nr. + * Units: m = MB, c = %, b/ns/nr = bytes/s */ export interface BeszelContainerStats { /** container name */ n: string; /** CPU usage (%) */ c: number; - /** memory usage (bytes) */ + /** memory usage (MB) */ m: number; /** network sent (bytes/s) — legacy, use b when available */ ns?: number; diff --git a/packages/integrations/src/mock/data/beszel.ts b/packages/integrations/src/mock/data/beszel.ts index 8788cf136..f5bc3ab73 100644 --- a/packages/integrations/src/mock/data/beszel.ts +++ b/packages/integrations/src/mock/data/beszel.ts @@ -10,7 +10,6 @@ import type { } from "../../beszel/beszel-types"; const GB = 1024 * 1024 * 1024; -const MB = 1024 * 1024; const KB = 1024; interface MockSystemDef { @@ -144,26 +143,27 @@ function generateSystemStatsSeries(count: number, sys: MockSystemDef): BeszelSys const netSendWalk = smoothWalk(500, 200, count, 10, 8000); const netRecvWalk = smoothWalk(800, 300, count, 10, 12000); - const memTotal = sys.mem; const diskTotal = rand(200, 2000) * GB; return cpuWalk.map((cpu, i) => { const memPct = memPctWalk[i] ?? sys.baseMem; const diskPct = diskPctWalk[i] ?? sys.baseDisk; + const memTotalGB = sys.mem / GB; + const diskTotalGB = diskTotal / GB; return { cpu, la: [cpu / 20 + rand(0, 0.5), cpu / 25 + rand(0, 0.3), cpu / 30 + rand(0, 0.2)] as [number, number, number], - m: memTotal, - mu: (memTotal * memPct) / 100, + m: memTotalGB, + mu: memTotalGB * memPct / 100, mp: memPct, - mb: rand(0.5, 4) * GB, - s: 4 * GB, - su: rand(0, 2) * GB, - d: diskTotal, - du: (diskTotal * diskPct) / 100, + mb: rand(0.5, 4), + s: 4, + su: rand(0, 2), + d: diskTotalGB, + du: diskTotalGB * diskPct / 100, dp: diskPct, - dr: (diskReadWalk[i] ?? 5) * MB, - dw: (diskWriteWalk[i] ?? 3) * MB, + dr: (diskReadWalk[i] ?? 5), + dw: (diskWriteWalk[i] ?? 3), ns: (netSendWalk[i] ?? 500) * KB, nr: (netRecvWalk[i] ?? 800) * KB, b: [(netSendWalk[i] ?? 500) * KB * 0.7, (netRecvWalk[i] ?? 800) * KB * 0.7] as [number, number], @@ -183,7 +183,7 @@ function generateContainerStatsSeries(count: number, profiles: typeof containerP walks.map(({ profile, cpuWalk, memWalk, netWalk }) => ({ n: profile.name, c: cpuWalk[i] ?? profile.cpuBase, - m: (memWalk[i] ?? profile.memMB) * MB, + m: memWalk[i] ?? profile.memMB, b: [(netWalk[i] ?? profile.netKB) * KB * 0.4, (netWalk[i] ?? profile.netKB) * KB * 0.6] as [number, number], })), ); @@ -264,13 +264,15 @@ export class BeszelMockService { const sys = resolveSystem(systemId); const intervalMinutes = typeToMinutes[type] ?? 1; const statsSeries = generateSystemStatsSeries(perPage, sys); - return buildTimeSeries( + const result = buildTimeSeries( systemId, perPage, intervalMinutes, type, statsSeries.map((stats) => ({ stats })), ); + + return result; } public async getContainerStatsAsync( @@ -284,13 +286,15 @@ export class BeszelMockService { .map((i) => containerProfiles[i]) .filter(Boolean) as typeof containerProfiles; const series = generateContainerStatsSeries(perPage, selectedProfiles); - return buildTimeSeries( + const result = buildTimeSeries( systemId, perPage, intervalMinutes, type, series.map((stats) => ({ stats })), ); + + return result; } public async getAlertsAsync(): Promise { diff --git a/packages/widgets/src/beszel-system-stats/component.tsx b/packages/widgets/src/beszel-system-stats/component.tsx index 73715839e..2612ee81a 100644 --- a/packages/widgets/src/beszel-system-stats/component.tsx +++ b/packages/widgets/src/beszel-system-stats/component.tsx @@ -63,23 +63,23 @@ export default function BeszelSystemStatsWidget({ { staleTime: 30 * 1000 }, ); - // BeszelSystemStats fields are documented in beszel-types.ts. - // mu/du = bytes, dr/dw = bytes/s, b = public bandwidth [sent,recv] bytes/s, ns/nr = all-interface bytes/s - const BYTES_TO_GB = 1024 * 1024 * 1024; + // BeszelSystemStats fields: storage values (m, mu, mb, d, du, s, su) are already in GB. + // Disk I/O (dr, dw) is in MB/s — scale to bytes/s for display formatters. + // Network (ns, nr, b) is in bytes/s. Container memory (m) is in MB. const cpuMap = useCallback((s: { cpu: number }) => ({ [t("chart.cpu.series")]: s.cpu }), [t]); const memoryMap = useCallback( (s: { mu: number; mb: number }) => ({ - [t("chart.memory.series")]: s.mu / BYTES_TO_GB, - [t("chart.memory.cache")]: (s.mb ?? 0) / BYTES_TO_GB, + [t("chart.memory.series")]: s.mu, + [t("chart.memory.cache")]: s.mb ?? 0, }), [t], ); - const diskMap = useCallback((s: { du: number }) => ({ [t("chart.disk.series")]: s.du / BYTES_TO_GB }), [t]); + const diskMap = useCallback((s: { du: number }) => ({ [t("chart.disk.series")]: s.du }), [t]); const diskIOMap = useCallback( (s: { dr?: number; dw?: number }) => ({ - [t("chart.diskIO.read")]: s.dr ?? 0, - [t("chart.diskIO.write")]: s.dw ?? 0, + [t("chart.diskIO.read")]: (s.dr ?? 0) * (1024 * 1024), + [t("chart.diskIO.write")]: (s.dw ?? 0) * (1024 * 1024), }), [t], ); diff --git a/packages/widgets/src/beszel/_shared/chart.tsx b/packages/widgets/src/beszel/_shared/chart.tsx index 6100a7d37..f7b735255 100644 --- a/packages/widgets/src/beszel/_shared/chart.tsx +++ b/packages/widgets/src/beszel/_shared/chart.tsx @@ -46,7 +46,8 @@ export const BeszelAreaChart = ({ yAxisFormatter, yAxisDomain, yAxisProps, style withDots={false} withXAxis withYAxis - style={{ minWidth: 0, ...style }} + w="100%" + style={{ minWidth: 0, minHeight: 0, ...style }} yAxisProps={{ ...yAxisBase, ...(yAxisDomain ? { domain: yAxisDomain } : {}), @@ -83,10 +84,12 @@ export const useContainerNames = (containerStats: BeszelContainerStatsRecord[] | type ContainerExtractor = (container: BeszelContainerStatsRecord["stats"][number] | undefined) => number; -// c = CPU (%), m = memory (bytes), b = bandwidth [sent,recv] (bytes/s), ns/nr = legacy net (bytes/s) +// c = CPU (%), m = memory (MB), b = bandwidth [sent,recv] (bytes/s), ns/nr = legacy net (bytes/s) +const MB = 1024 * 1024; + const defaultContainerExtractors: Record = { cpu: (c) => c?.c ?? 0, - memory: (c) => c?.m ?? 0, + memory: (c) => (c?.m ?? 0) * MB, network: (c) => (c?.b ? c.b[0] + c.b[1] : (c?.ns ?? 0) + (c?.nr ?? 0)), };