diff --git a/src/commands/diagnose/metrics.test.ts b/src/commands/diagnose/metrics.test.ts new file mode 100644 index 0000000..a119911 --- /dev/null +++ b/src/commands/diagnose/metrics.test.ts @@ -0,0 +1,23 @@ +import { describe, it, expect } from 'vitest'; +import { formatValue } from './metrics.js'; + +describe('formatValue', () => { + it('formats disk byte counters as sizes, not percentages', () => { + expect(formatValue('disk_total', 8511270912)).toBe('7.9 GB'); + expect(formatValue('disk_used', 1073741824)).toBe('1.0 GB'); + expect(formatValue('disk_database', 5242880)).toBe('5.0 MB'); + expect(formatValue('disk_wal', 2048)).toBe('2.0 KB'); + expect(formatValue('disk_total', 2199023255552)).toBe('2.0 TB'); + }); + + it('still formats percentage metrics with a percent sign', () => { + expect(formatValue('disk_usage', 42.1)).toBe('42.1%'); + expect(formatValue('cpu_usage', 7)).toBe('7.0%'); + expect(formatValue('memory_usage', 63.25)).toBe('63.3%'); + }); + + it('formats network metrics as a rate', () => { + expect(formatValue('network_in', 512)).toBe('512.0 B/s'); + expect(formatValue('network_out', 1536)).toBe('1.5 KB/s'); + }); +}); diff --git a/src/commands/diagnose/metrics.ts b/src/commands/diagnose/metrics.ts index 6b3d91b..a39e237 100644 --- a/src/commands/diagnose/metrics.ts +++ b/src/commands/diagnose/metrics.ts @@ -29,23 +29,39 @@ const METRIC_LABELS: Record = { cpu_usage: 'CPU Usage', memory_usage: 'Memory Usage', disk_usage: 'Disk Usage', + disk_used: 'Disk Used', + disk_total: 'Disk Total', + disk_database: 'Disk Database', + disk_wal: 'Disk WAL', network_in: 'Network In', network_out: 'Network Out', }; const NETWORK_METRICS = new Set(['network_in', 'network_out']); -function formatValue(metric: string, value: number): string { +/** Raw byte counters — rendered as sizes, not percentages. */ +const BYTE_METRICS = new Set(['disk_used', 'disk_total', 'disk_database', 'disk_wal']); + +export function formatValue(metric: string, value: number): string { if (NETWORK_METRICS.has(metric)) { return formatBytes(value) + '/s'; } + if (BYTE_METRICS.has(metric)) { + return formatBytes(value); + } return `${value.toFixed(1)}%`; } function formatBytes(bytes: number): string { - if (bytes < 1024) return `${bytes.toFixed(1)} B`; - if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; - return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; + const KB = 1024; + const MB = KB * 1024; + const GB = MB * 1024; + const TB = GB * 1024; + if (bytes < KB) return `${bytes.toFixed(1)} B`; + if (bytes < MB) return `${(bytes / KB).toFixed(1)} KB`; + if (bytes < GB) return `${(bytes / MB).toFixed(1)} MB`; + if (bytes < TB) return `${(bytes / GB).toFixed(1)} GB`; + return `${(bytes / TB).toFixed(1)} TB`; } function computeStats(data: MetricDataPoint[]): { latest: number; avg: number; max: number } {