fix(collector): stop NVIDIA enrichment from clobbering PCIe status

enrichPCIeWithNVIDIAData unconditionally overwrote dev.Status after
collectPCIe() had already flagged a Warning/Critical (e.g. PCIe link
speed degraded), so a clean ECC/remap/reset readout silently downgraded
that finding back to OK while leaving the stale ErrorDescription behind.

Add a severity-ordered merge (OK/Unknown < Warning < Critical) shared
via mergeDeviceStatus in contract.go, and route both the NVIDIA status
calculation and the driver-unavailable fallback through it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Chusavitin
2026-08-04 17:28:47 +03:00
co-authored by Claude Sonnet 5
parent 6c8be629d2
commit a34e823f82
3 changed files with 153 additions and 8 deletions
+44 -1
View File
@@ -1,6 +1,9 @@
package collector
import "strings"
import (
"bee/audit/internal/schema"
"strings"
)
const (
statusOK = "OK"
@@ -62,3 +65,43 @@ func isRAIDClass(class string) bool {
return false
}
}
// statusSeverity ranks component statuses so merges can only escalate, never
// downgrade. Unknown ranks with OK: it means "couldn't tell", not "healthy",
// so it must not silently clear a Warning/Critical raised by an earlier stage.
func statusSeverity(status string) int {
switch strings.TrimSpace(status) {
case statusCritical:
return 3
case statusWarning:
return 2
case statusOK:
return 1
case statusUnknown:
return 1
default:
return 0
}
}
// mergeDeviceStatus applies status/description to dev only if it is at least
// as severe as whatever is already set. This lets later enrichment stages
// (e.g. NVIDIA telemetry) report their own findings without silently
// clobbering a Warning/Critical raised earlier in the collector pipeline
// (e.g. a PCIe link-speed degradation).
func mergeDeviceStatus(dev *schema.HardwarePCIeDevice, status, description string) {
if dev == nil || status == "" {
return
}
current := ""
if dev.Status != nil {
current = strings.TrimSpace(*dev.Status)
}
if current != "" && current != statusUnknown && statusSeverity(status) <= statusSeverity(current) {
return
}
dev.Status = &status
if strings.TrimSpace(description) != "" {
dev.ErrorDescription = &description
}
}