import * as fs from 'fs'; import * as os from 'os'; export interface ISystemUsageResult { cpuPercent: number; // 0-100% system-wide CPU utilization memTotalBytes: number; // total physical RAM memAvailableBytes: number; // available memory memUsedBytes: number; // memTotal - memAvailable memUsedPercent: number; // 0-100% loadAvg1: number; // 1-min load average loadAvg5: number; // 5-min load average loadAvg15: number; // 15-min load average } // History for system CPU delta tracking interface ICpuSnapshot { idle: number; total: number; } let prevCpuSnapshot: ICpuSnapshot | null = null; function readProcStat(): ICpuSnapshot | null { try { const content = fs.readFileSync('/proc/stat', 'utf8'); const firstLine = content.split('\n')[0]; // "cpu user nice system idle iowait irq softirq steal ..." const parts = firstLine.split(/\s+/).slice(1).map(Number); // parts: [user, nice, system, idle, iowait, irq, softirq, steal, ...] const idle = parts[3] + (parts[4] || 0); // idle + iowait const total = parts.reduce((sum, v) => sum + v, 0); return { idle, total }; } catch { return null; } } function getMemoryInfo(): { totalBytes: number; availableBytes: number } { try { const content = fs.readFileSync('/proc/meminfo', 'utf8'); let memTotal = 0; let memAvailable = 0; for (const line of content.split('\n')) { if (line.startsWith('MemTotal:')) { memTotal = parseInt(line.split(/\s+/)[1], 10) * 1024; // kB to bytes } else if (line.startsWith('MemAvailable:')) { memAvailable = parseInt(line.split(/\s+/)[1], 10) * 1024; } } if (memTotal > 0 && memAvailable > 0) { return { totalBytes: memTotal, availableBytes: memAvailable }; } } catch { // fall through to os fallback } // Fallback using os module const totalBytes = os.totalmem(); const availableBytes = os.freemem(); return { totalBytes, availableBytes }; } export async function getSystemUsage(): Promise { // CPU let cpuPercent = 0; const currentSnapshot = readProcStat(); if (currentSnapshot && prevCpuSnapshot) { const totalDelta = currentSnapshot.total - prevCpuSnapshot.total; const idleDelta = currentSnapshot.idle - prevCpuSnapshot.idle; if (totalDelta > 0) { cpuPercent = ((totalDelta - idleDelta) / totalDelta) * 100; } } if (currentSnapshot) { prevCpuSnapshot = currentSnapshot; } // Memory const mem = getMemoryInfo(); const memUsedBytes = mem.totalBytes - mem.availableBytes; const memUsedPercent = mem.totalBytes > 0 ? (memUsedBytes / mem.totalBytes) * 100 : 0; // Load averages const [loadAvg1, loadAvg5, loadAvg15] = os.loadavg(); return { cpuPercent, memTotalBytes: mem.totalBytes, memAvailableBytes: mem.availableBytes, memUsedBytes, memUsedPercent, loadAvg1, loadAvg5, loadAvg15, }; }