package collector import ( "bee/audit/internal/schema" "fmt" "time" ) func BuildHealthSummary(snap schema.HardwareSnapshot) *schema.HardwareHealthSummary { summary := &schema.HardwareHealthSummary{ Status: statusOK, CollectedAt: time.Now().UTC().Format(time.RFC3339), } for _, dimm := range snap.Memory { switch derefString(dimm.Status) { case statusWarning: summary.MemoryWarn++ summary.Warnings = append(summary.Warnings, formatMemorySummary(dimm)) case statusCritical: summary.MemoryFail++ summary.Failures = append(summary.Failures, formatMemorySummary(dimm)) case statusEmpty: summary.EmptyDIMMs++ } } for _, disk := range snap.Storage { switch derefString(disk.Status) { case statusWarning: summary.StorageWarn++ summary.Warnings = append(summary.Warnings, formatStorageSummary(disk)) case statusCritical: summary.StorageFail++ summary.Failures = append(summary.Failures, formatStorageSummary(disk)) } } for _, dev := range snap.PCIeDevices { switch derefString(dev.Status) { case statusWarning: summary.PCIeWarn++ summary.Warnings = append(summary.Warnings, formatPCIeSummary(dev)) case statusCritical: summary.PCIeFail++ summary.Failures = append(summary.Failures, formatPCIeSummary(dev)) } } for _, psu := range snap.PowerSupplies { if psu.Present != nil && !*psu.Present { summary.MissingPSUs++ } switch derefString(psu.Status) { case statusWarning: summary.PSUWarn++ summary.Warnings = append(summary.Warnings, formatPSUSummary(psu)) case statusCritical: summary.PSUFail++ summary.Failures = append(summary.Failures, formatPSUSummary(psu)) } } if len(summary.Failures) > 0 || summary.StorageFail > 0 || summary.PCIeFail > 0 || summary.PSUFail > 0 || summary.MemoryFail > 0 { summary.Status = statusCritical } else if len(summary.Warnings) > 0 || summary.StorageWarn > 0 || summary.PCIeWarn > 0 || summary.PSUWarn > 0 || summary.MemoryWarn > 0 { summary.Status = statusWarning } if len(summary.Warnings) == 0 { summary.Warnings = nil } if len(summary.Failures) == 0 { summary.Failures = nil } return summary } func derefString(value *string) string { if value == nil { return "" } return *value } func preferredName(model, serial, slot *string) string { switch { case model != nil && *model != "": return *model case serial != nil && *serial != "": return *serial case slot != nil && *slot != "": return *slot default: return "unknown" } } func formatStorageSummary(disk schema.HardwareStorage) string { return fmt.Sprintf("storage %s status=%s", preferredName(disk.Model, disk.SerialNumber, disk.Slot), derefString(disk.Status)) } func formatPCIeSummary(dev schema.HardwarePCIeDevice) string { return fmt.Sprintf("pcie %s status=%s", preferredName(dev.Model, dev.SerialNumber, dev.BDF), derefString(dev.Status)) } func formatPSUSummary(psu schema.HardwarePowerSupply) string { return fmt.Sprintf("psu %s status=%s", preferredName(psu.Model, psu.SerialNumber, psu.Slot), derefString(psu.Status)) } func formatMemorySummary(dimm schema.HardwareMemory) string { return fmt.Sprintf("memory %s status=%s", preferredName(dimm.PartNumber, dimm.SerialNumber, dimm.Slot), derefString(dimm.Status)) }