fix(agent): warn on critical ATA SMART attributes (#2275)

This commit is contained in:
Aditya Raj Singh
2026-08-30 11:23:52 -04:00
committed by GitHub
parent e235c9935c
commit fa9de55433
2 changed files with 51 additions and 0 deletions
+3
View File
@@ -931,6 +931,9 @@ func (sm *SmartManager) parseSmartForSata(output []byte, deviceType string) (boo
if parsed, ok := smart.ParseSmartRawValueString(attr.Raw.String); ok {
rawValue = parsed
}
if smartData.SmartStatus == "PASSED" && rawValue > 0 && (attr.ID == 5 || attr.ID == 197 || attr.ID == 198) {
smartData.SmartStatus = "WARNING"
}
smartAttr := &smart.SmartAttribute{
ID: attr.ID,
Name: attr.Name,
+48
View File
@@ -4,8 +4,10 @@ package agent
import (
"errors"
"fmt"
"os"
"path/filepath"
"strconv"
"testing"
"github.com/henrygd/beszel/internal/entities/smart"
@@ -88,6 +90,52 @@ func TestParseSmartForSata(t *testing.T) {
}
}
func TestParseSmartForSataWarnsForCriticalAttributes(t *testing.T) {
for _, attrID := range []int{5, 197, 198} {
t.Run("attribute "+strconv.Itoa(attrID), func(t *testing.T) {
jsonPayload := []byte(fmt.Sprintf(`{
"smartctl": {"exit_status": 0},
"device": {"name": "/dev/sda", "type": "sat"},
"model_name": "Example",
"serial_number": "WARNING%d",
"smart_status": {"passed": true},
"temperature": {"current": 30},
"ata_smart_attributes": {"table": [{"id": %d, "raw": {"value": 1, "string": "1"}}]}
}`, attrID, attrID))
sm := &SmartManager{SmartDataMap: make(map[string]*smart.SmartData)}
hasData, _ := sm.parseSmartForSata(jsonPayload, "")
require.True(t, hasData)
assert.Equal(t, "WARNING", sm.SmartDataMap[fmt.Sprintf("WARNING%d", attrID)].SmartStatus)
})
}
}
func TestParseSmartForSataPreservesFailedAndUnknownStatus(t *testing.T) {
for _, test := range []struct {
name string
temperature int
want string
}{
{name: "failed", temperature: 30, want: "FAILED"},
{name: "unknown", want: "UNKNOWN"},
} {
t.Run(test.name, func(t *testing.T) {
jsonPayload := []byte(fmt.Sprintf(`{
"device": {"name": "/dev/sda", "type": "sat"},
"serial_number": "PRESERVE%s",
"temperature": {"current": %d},
"ata_smart_attributes": {"table": [{"id": 197, "raw": {"value": 1, "string": "1"}}]}
}`, test.name, test.temperature))
sm := &SmartManager{SmartDataMap: make(map[string]*smart.SmartData)}
hasData, _ := sm.parseSmartForSata(jsonPayload, "")
require.True(t, hasData)
assert.Equal(t, test.want, sm.SmartDataMap["PRESERVE"+test.name].SmartStatus)
})
}
}
func TestParseSmartForSataDeviceStatisticsTemperature(t *testing.T) {
jsonPayload := []byte(`{
"smartctl": {"exit_status": 0},