fix(monitoring): retain intermittent FreeBSD SMART data

This commit is contained in:
rcourtman
2026-03-10 22:52:25 +00:00
parent 1a582ccc35
commit afcfb23a30
2 changed files with 77 additions and 1 deletions
+10 -1
View File
@@ -3071,6 +3071,15 @@ func (m *Monitor) ApplyHostReport(report agentshost.Report, tokenRecord *config.
memory.Usage = safePercentage(float64(memory.Used), float64(memory.Total))
}
smartSensors := convertAgentSMARTToModels(report.Sensors.SMART)
reportPlatform := strings.TrimSpace(strings.ToLower(report.Host.Platform))
if len(smartSensors) == 0 && hasPrevious && len(previous.Sensors.SMART) > 0 &&
(reportPlatform == "freebsd" || strings.EqualFold(previous.Platform, "freebsd")) {
// FreeBSD SMART collection can be intermittent; avoid wiping previously
// known disk temperatures on an otherwise healthy host report.
smartSensors = append([]models.HostDiskSMART(nil), previous.Sensors.SMART...)
}
disks := make([]models.Disk, 0, len(report.Disks))
for _, disk := range report.Disks {
// Filter virtual/system filesystems and read-only filesystems to avoid cluttering
@@ -3174,7 +3183,7 @@ func (m *Monitor) ApplyHostReport(report agentshost.Report, tokenRecord *config.
TemperatureCelsius: cloneStringFloatMap(report.Sensors.TemperatureCelsius),
FanRPM: cloneStringFloatMap(report.Sensors.FanRPM),
Additional: cloneStringFloatMap(report.Sensors.Additional),
SMART: convertAgentSMARTToModels(report.Sensors.SMART),
SMART: smartSensors,
},
RAID: raid,
Ceph: cephData,
@@ -179,6 +179,73 @@ func TestApplyHostReportPersistsAndRemoveHostAgentClearsRuntime(t *testing.T) {
}
}
func TestApplyHostReportPreservesFreeBSDSMARTWhenNextReportOmitsIt(t *testing.T) {
t.Helper()
monitor := &Monitor{
state: models.NewState(),
alertManager: alerts.NewManager(),
hostTokenBindings: make(map[string]string),
config: &config.Config{},
rateTracker: NewRateTracker(),
}
t.Cleanup(func() { monitor.alertManager.Stop() })
now := time.Now().UTC()
first := agentshost.Report{
Agent: agentshost.AgentInfo{
ID: "agent-freebsd",
Version: "1.0.0",
IntervalSeconds: 30,
},
Host: agentshost.HostInfo{
ID: "machine-freebsd",
Hostname: "pfsense.local",
Platform: "freebsd",
},
Timestamp: now,
Metrics: agentshost.Metrics{
CPUUsagePercent: 5.5,
},
Sensors: agentshost.Sensors{
SMART: []agentshost.DiskSMART{
{
Device: "ada0",
Model: "Disk 0",
Temperature: 33,
Health: "PASSED",
},
},
},
}
host, err := monitor.ApplyHostReport(first, nil)
if err != nil {
t.Fatalf("ApplyHostReport first: %v", err)
}
if len(host.Sensors.SMART) != 1 {
t.Fatalf("expected initial SMART data, got %d entries", len(host.Sensors.SMART))
}
second := first
second.Timestamp = now.Add(30 * time.Second)
second.Sensors = agentshost.Sensors{}
host, err = monitor.ApplyHostReport(second, nil)
if err != nil {
t.Fatalf("ApplyHostReport second: %v", err)
}
if len(host.Sensors.SMART) != 1 {
t.Fatalf("expected SMART data to be preserved, got %d entries", len(host.Sensors.SMART))
}
if host.Sensors.SMART[0].Device != "ada0" {
t.Fatalf("expected preserved SMART device ada0, got %q", host.Sensors.SMART[0].Device)
}
if host.Sensors.SMART[0].Temperature != 33 {
t.Fatalf("expected preserved SMART temperature 33, got %d", host.Sensors.SMART[0].Temperature)
}
}
func TestClearUnauthenticatedAgentsClearsPersistedHostRuntime(t *testing.T) {
dataDir := t.TempDir()
runtimeStore := config.NewHostRuntimeStore(dataDir, nil)