diff --git a/beszel/internal/agent/sensors.go b/beszel/internal/agent/sensors.go index 6d3292e..a82bf69 100644 --- a/beszel/internal/agent/sensors.go +++ b/beszel/internal/agent/sensors.go @@ -13,26 +13,31 @@ import ( ) type SensorConfig struct { - context context.Context - sensors map[string]struct{} - primarySensor string - isBlacklist bool - hasWildcards bool + context context.Context + sensors map[string]struct{} + primarySensor string + isBlacklist bool + hasWildcards bool + skipCollection bool } func (a *Agent) newSensorConfig() *SensorConfig { primarySensor, _ := GetEnv("PRIMARY_SENSOR") sysSensors, _ := GetEnv("SYS_SENSORS") - sensors, _ := GetEnv("SENSORS") + sensorsEnvVal, sensorsSet := GetEnv("SENSORS") + skipCollection := sensorsSet && sensorsEnvVal == "" - return a.newSensorConfigWithEnv(primarySensor, sysSensors, sensors) + return a.newSensorConfigWithEnv(primarySensor, sysSensors, sensorsEnvVal, skipCollection) } // newSensorConfigWithEnv creates a SensorConfig with the provided environment variables -func (a *Agent) newSensorConfigWithEnv(primarySensor, sysSensors, sensors string) *SensorConfig { +// sensorsSet indicates if the SENSORS environment variable was explicitly set (even to empty string) +func (a *Agent) newSensorConfigWithEnv(primarySensor, sysSensors, sensorsEnvVal string, skipCollection bool) *SensorConfig { config := &SensorConfig{ - context: context.Background(), - primarySensor: primarySensor, + context: context.Background(), + primarySensor: primarySensor, + skipCollection: skipCollection, + sensors: make(map[string]struct{}), } // Set sensors context (allows overriding sys location for sensors) @@ -43,22 +48,18 @@ func (a *Agent) newSensorConfigWithEnv(primarySensor, sysSensors, sensors string ) } - // Set sensors whitelist - if sensors != "" { - // handle blacklist - if strings.HasPrefix(sensors, "-") { - config.isBlacklist = true - sensors = sensors[1:] - } + // handle blacklist + if strings.HasPrefix(sensorsEnvVal, "-") { + config.isBlacklist = true + sensorsEnvVal = sensorsEnvVal[1:] + } - config.sensors = make(map[string]struct{}) - for sensor := range strings.SplitSeq(sensors, ",") { - sensor = strings.TrimSpace(sensor) - if sensor != "" { - config.sensors[sensor] = struct{}{} - if strings.Contains(sensor, "*") { - config.hasWildcards = true - } + for sensor := range strings.SplitSeq(sensorsEnvVal, ",") { + sensor = strings.TrimSpace(sensor) + if sensor != "" { + config.sensors[sensor] = struct{}{} + if strings.Contains(sensor, "*") { + config.hasWildcards = true } } } @@ -69,7 +70,7 @@ func (a *Agent) newSensorConfigWithEnv(primarySensor, sysSensors, sensors string // updateTemperatures updates the agent with the latest sensor temperatures func (a *Agent) updateTemperatures(systemStats *system.Stats) { // skip if sensors whitelist is set to empty string - if a.sensorConfig.sensors != nil && len(a.sensorConfig.sensors) == 0 { + if a.sensorConfig.skipCollection { slog.Debug("Skipping temperature collection") return } @@ -113,8 +114,8 @@ func (a *Agent) updateTemperatures(systemStats *system.Stats) { // isValidSensor checks if a sensor is valid based on the sensor name and the sensor config func isValidSensor(sensorName string, config *SensorConfig) bool { - // If no sensors configuration, everything is valid - if config.sensors == nil { + // if no sensors configured, everything is valid + if len(config.sensors) == 0 { return true } @@ -123,7 +124,7 @@ func isValidSensor(sensorName string, config *SensorConfig) bool { return !config.isBlacklist } - // If no wildcards, return false if blacklist, true if whitelist + // If no wildcards, return true if blacklist, false if whitelist if !config.hasWildcards { return config.isBlacklist } diff --git a/beszel/internal/agent/sensors_test.go b/beszel/internal/agent/sensors_test.go index 20f4020..22e1a5c 100644 --- a/beszel/internal/agent/sensors_test.go +++ b/beszel/internal/agent/sensors_test.go @@ -97,10 +97,13 @@ func TestIsValidSensor(t *testing.T) { expectedValid: true, }, { - name: "Nil sensor config", + name: "No sensors configured", sensorName: "any_temp", config: &SensorConfig{ - sensors: nil, + sensors: map[string]struct{}{}, + isBlacklist: false, + hasWildcards: false, + skipCollection: false, }, expectedValid: true, }, @@ -162,6 +165,7 @@ func TestNewSensorConfigWithEnv(t *testing.T) { primarySensor string sysSensors string sensors string + skipCollection bool expectedConfig *SensorConfig }{ { @@ -170,22 +174,38 @@ func TestNewSensorConfigWithEnv(t *testing.T) { sysSensors: "", sensors: "", expectedConfig: &SensorConfig{ - context: context.Background(), - primarySensor: "", - sensors: nil, - isBlacklist: false, - hasWildcards: false, + context: context.Background(), + primarySensor: "", + sensors: map[string]struct{}{}, + isBlacklist: false, + hasWildcards: false, + skipCollection: false, }, }, { - name: "Primary sensor only", + name: "Explicitly set to empty string", + primarySensor: "", + sysSensors: "", + sensors: "", + skipCollection: true, + expectedConfig: &SensorConfig{ + context: context.Background(), + primarySensor: "", + sensors: map[string]struct{}{}, + isBlacklist: false, + hasWildcards: false, + skipCollection: true, + }, + }, + { + name: "Primary sensor only - should create sensor map", primarySensor: "cpu_temp", sysSensors: "", sensors: "", expectedConfig: &SensorConfig{ context: context.Background(), primarySensor: "cpu_temp", - sensors: nil, + sensors: map[string]struct{}{}, isBlacklist: false, hasWildcards: false, }, @@ -238,6 +258,22 @@ func TestNewSensorConfigWithEnv(t *testing.T) { hasWildcards: true, }, }, + { + name: "Sensors with whitespace", + primarySensor: "cpu_temp", + sysSensors: "", + sensors: "cpu_*, gpu_temp", + expectedConfig: &SensorConfig{ + context: context.Background(), + primarySensor: "cpu_temp", + sensors: map[string]struct{}{ + "cpu_*": {}, + "gpu_temp": {}, + }, + isBlacklist: false, + hasWildcards: true, + }, + }, { name: "With SYS_SENSORS path", primarySensor: "cpu_temp", @@ -256,7 +292,7 @@ func TestNewSensorConfigWithEnv(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - result := agent.newSensorConfigWithEnv(tt.primarySensor, tt.sysSensors, tt.sensors) + result := agent.newSensorConfigWithEnv(tt.primarySensor, tt.sysSensors, tt.sensors, tt.skipCollection) // Check primary sensor assert.Equal(t, tt.expectedConfig.primarySensor, result.primarySensor)