import si from 'systeminformation'; interface SystemMetrics { cpu: { usage: number; cores: number; model: string; }; memory: { total: number; used: number; free: number; usagePercent: number; }; disk: { total: number; used: number; free: number; usagePercent: number; }; uptime: string; processes: { total: number; running: number; sleeping: number; }; } // Cache system metrics to avoid excessive system calls let metricsCache: SystemMetrics | null = null; let lastCacheTime = 0; const CACHE_DURATION = 30000; // 30 seconds export async function getSystemMetrics(): Promise { const now = Date.now(); // Return cached data if still valid if (metricsCache && (now - lastCacheTime) < CACHE_DURATION) { console.log('📊 Returning cached system metrics'); return metricsCache; } try { console.log('🔄 Fetching fresh system metrics...'); // Get all metrics in parallel with individual error handling const results = await Promise.allSettled([ si.cpu(), si.mem(), si.fsSize(), si.currentLoad(), si.processes(), si.time() ]); // Extract data with fallbacks for failed promises const cpuData = results[0].status === 'fulfilled' ? results[0].value : { cores: 0, brand: 'Unknown' }; const memData = results[1].status === 'fulfilled' ? results[1].value : { total: 0, used: 0, free: 0 }; const fsData = results[2].status === 'fulfilled' ? results[2].value : []; const currentLoad = results[3].status === 'fulfilled' ? results[3].value : { currentLoad: 0 }; const processData = results[4].status === 'fulfilled' ? results[4].value : { all: 0, running: 0, sleeping: 0 }; const uptimeData = results[5].status === 'fulfilled' ? results[5].value : { uptime: 0 }; // Log any failures results.forEach((result, index) => { if (result.status === 'rejected') { const names = ['CPU', 'Memory', 'Filesystem', 'CPU Load', 'Processes', 'Uptime']; console.warn(`⚠️ ${names[index]} data failed:`, result.reason?.message || result.reason); } }); // Calculate disk totals across all mounted filesystems const diskTotals = (fsData as any[]).reduce((acc: { total: number; used: number }, fs: any) => { // Skip special filesystems and focus on main storage if (fs.type && !['tmpfs', 'devtmpfs', 'proc', 'sysfs'].includes(fs.type.toLowerCase())) { acc.total += fs.size || 0; acc.used += fs.used || 0; } return acc; }, { total: 0, used: 0 }); const diskFree = diskTotals.total - diskTotals.used; const diskUsagePercent = diskTotals.total > 0 ? Math.round((diskTotals.used / diskTotals.total) * 100) : 0; // Format uptime const formatUptime = (seconds: number): string => { const days = Math.floor(seconds / 86400); const hours = Math.floor((seconds % 86400) / 3600); const minutes = Math.floor((seconds % 3600) / 60); if (days > 0) { return `${days}d ${hours}h ${minutes}m`; } else if (hours > 0) { return `${hours}h ${minutes}m`; } else { return `${minutes}m`; } }; // Build metrics object const metrics: SystemMetrics = { cpu: { usage: Math.round(currentLoad.currentLoad || 0), cores: cpuData.cores || 0, model: cpuData.brand || 'Unknown' }, memory: { total: memData.total || 0, used: memData.used || 0, free: memData.free || 0, usagePercent: memData.total > 0 ? Math.round((memData.used / memData.total) * 100) : 0 }, disk: { total: diskTotals.total, used: diskTotals.used, free: diskFree, usagePercent: diskUsagePercent }, uptime: formatUptime(uptimeData.uptime || 0), processes: { total: processData.all || 0, running: processData.running || 0, sleeping: processData.sleeping || 0 } }; // Cache the results metricsCache = metrics; lastCacheTime = now; console.log('✅ System metrics fetched successfully:', { cpu: `${metrics.cpu.usage}%`, memory: `${metrics.memory.usagePercent}%`, disk: `${metrics.disk.usagePercent}%`, uptime: metrics.uptime }); return metrics; } catch (error) { console.error('❌ Failed to fetch system metrics:', error); // Return fallback metrics on error const fallbackMetrics: SystemMetrics = { cpu: { usage: 0, cores: 0, model: 'Unknown' }, memory: { total: 0, used: 0, free: 0, usagePercent: 0 }, disk: { total: 0, used: 0, free: 0, usagePercent: 0 }, uptime: '0m', processes: { total: 0, running: 0, sleeping: 0 } }; return fallbackMetrics; } } // Helper function to format bytes to human readable format export function formatBytes(bytes: number): string { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB', 'TB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]; } // Helper function to get system health status export function getSystemHealthStatus(metrics: SystemMetrics): 'healthy' | 'degraded' | 'unhealthy' { const { cpu, memory, disk } = metrics; // Define thresholds const criticalThresholds = { cpu: 90, memory: 95, disk: 95 }; const warningThresholds = { cpu: 70, memory: 80, disk: 85 }; // Check for critical issues if (cpu.usage > criticalThresholds.cpu || memory.usagePercent > criticalThresholds.memory || disk.usagePercent > criticalThresholds.disk) { return 'unhealthy'; } // Check for warning issues if (cpu.usage > warningThresholds.cpu || memory.usagePercent > warningThresholds.memory || disk.usagePercent > warningThresholds.disk) { return 'degraded'; } return 'healthy'; }