package main import ( "fmt" "strings" ) // Health score weights and thresholds. const ( // Weights. healthCPUWeight = 30.0 healthMemWeight = 25.0 healthDiskWeight = 20.0 healthThermalWeight = 15.0 healthIOWeight = 10.0 // CPU. cpuNormalThreshold = 30.0 cpuHighThreshold = 70.0 // Memory. memNormalThreshold = 50.0 memHighThreshold = 80.0 memPressureWarnPenalty = 5.0 memPressureCritPenalty = 15.0 // Disk. diskWarnThreshold = 70.0 diskCritThreshold = 90.0 // Thermal. thermalNormalThreshold = 60.0 thermalHighThreshold = 85.0 // Disk IO (MB/s). ioNormalThreshold = 50.0 ioHighThreshold = 150.0 ) func calculateHealthScore(cpu CPUStatus, mem MemoryStatus, disks []DiskStatus, diskIO DiskIOStatus, thermal ThermalStatus) (int, string) { score := 100.0 issues := []string{} // CPU penalty. cpuPenalty := 0.0 if cpu.Usage > cpuNormalThreshold { if cpu.Usage > cpuHighThreshold { cpuPenalty = healthCPUWeight * (cpu.Usage - cpuNormalThreshold) / cpuHighThreshold } else { cpuPenalty = (healthCPUWeight / 2) * (cpu.Usage - cpuNormalThreshold) / (cpuHighThreshold - cpuNormalThreshold) } } score -= cpuPenalty if cpu.Usage > cpuHighThreshold { issues = append(issues, "High CPU") } // Memory penalty. memPenalty := 0.0 if mem.UsedPercent > memNormalThreshold { if mem.UsedPercent > memHighThreshold { memPenalty = healthMemWeight * (mem.UsedPercent - memNormalThreshold) / memNormalThreshold } else { memPenalty = (healthMemWeight / 2) * (mem.UsedPercent - memNormalThreshold) / (memHighThreshold - memNormalThreshold) } } score -= memPenalty if mem.UsedPercent > memHighThreshold { issues = append(issues, "High Memory") } // Memory pressure penalty. // Memory pressure penalty. switch mem.Pressure { case "warn": score -= memPressureWarnPenalty issues = append(issues, "Memory Pressure") case "critical": score -= memPressureCritPenalty issues = append(issues, "Critical Memory") } // Disk penalty. diskPenalty := 0.0 if len(disks) > 0 { diskUsage := disks[0].UsedPercent if diskUsage > diskWarnThreshold { if diskUsage > diskCritThreshold { diskPenalty = healthDiskWeight * (diskUsage - diskWarnThreshold) / (100 - diskWarnThreshold) } else { diskPenalty = (healthDiskWeight / 2) * (diskUsage - diskWarnThreshold) / (diskCritThreshold - diskWarnThreshold) } } score -= diskPenalty if diskUsage > diskCritThreshold { issues = append(issues, "Disk Almost Full") } } // Thermal penalty. thermalPenalty := 0.0 if thermal.CPUTemp > 0 { if thermal.CPUTemp > thermalNormalThreshold { if thermal.CPUTemp > thermalHighThreshold { thermalPenalty = healthThermalWeight issues = append(issues, "Overheating") } else { thermalPenalty = healthThermalWeight * (thermal.CPUTemp - thermalNormalThreshold) / (thermalHighThreshold - thermalNormalThreshold) } } score -= thermalPenalty } // Disk IO penalty. ioPenalty := 0.0 totalIO := diskIO.ReadRate + diskIO.WriteRate if totalIO > ioNormalThreshold { if totalIO > ioHighThreshold { ioPenalty = healthIOWeight issues = append(issues, "Heavy Disk IO") } else { ioPenalty = healthIOWeight * (totalIO - ioNormalThreshold) / (ioHighThreshold - ioNormalThreshold) } } score -= ioPenalty // Clamp score. if score < 0 { score = 0 } if score > 100 { score = 100 } // Build message. var msg string switch { case score >= 90: msg = "Excellent" case score >= 75: msg = "Good" case score >= 60: msg = "Fair" case score >= 40: msg = "Poor" default: msg = "Critical" } if len(issues) > 0 { msg = msg + ": " + strings.Join(issues, ", ") } return int(score), msg } func formatUptime(secs uint64) string { days := secs / 86400 hours := (secs % 86400) / 3600 mins := (secs % 3600) / 60 if days > 0 { return fmt.Sprintf("%dd %dh %dm", days, hours, mins) } if hours > 0 { return fmt.Sprintf("%dh %dm", hours, mins) } return fmt.Sprintf("%dm", mins) }