From 574c4cf9dd693bd7f3de88314f99e6ec89e906d5 Mon Sep 17 00:00:00 2001 From: yi111 <153097222+Yi-111-a@users.noreply.github.com> Date: Tue, 20 Oct 2026 01:09:05 +0800 Subject: [PATCH] fix(agent): claim sensor names before filtering so excludes don't rename (#2645) updateTemperatures detected duplicate SensorKeys by looking at the output map, which only holds sensors that passed every filter. A sensor dropped by SENSORS or SKIP_GPU therefore never claimed its name, so excluding the first of two same-named sensors renamed the second one from nvme_sensor_2_4 to nvme_sensor_2 and dropped it too, making it impossible to exclude just one. Track handed-out names in a separate set that is populated before any filter runs, so a sensor's key depends only on the hardware list. --- agent/sensors.go | 17 ++++++++++----- agent/sensors_test.go | 48 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/agent/sensors.go b/agent/sensors.go index 4265cc616..a50e99d4d 100644 --- a/agent/sensors.go +++ b/agent/sensors.go @@ -151,12 +151,24 @@ func (a *Agent) updateTemperatures(systemStats *system.Stats) { } systemStats.Temperatures = make(map[string]float64, len(temps)) + // claimed tracks every name handed out, including names of sensors that are + // dropped below, so a sensor's key never depends on which sensors were filtered + claimed := make(map[string]struct{}, len(temps)) for i, sensor := range temps { // check for malformed strings on darwin (gopsutil/issues/1832) if runtime.GOOS == "darwin" && !utf8.ValidString(sensor.SensorKey) { continue } + // claim a name before any filtering, so excluding a sensor does not + // rename the sensors after it + sensorName := sensor.SensorKey + if _, ok := claimed[sensorName]; ok { + // if key already claimed, append int to key + sensorName = sensorName + "_" + strconv.Itoa(i) + } + claimed[sensorName] = struct{}{} + // scale temperature if sensor.Temperature != 0 && sensor.Temperature < 1 { sensor.Temperature = scaleTemperature(sensor.Temperature) @@ -165,11 +177,6 @@ func (a *Agent) updateTemperatures(systemStats *system.Stats) { if sensor.Temperature <= 0 || sensor.Temperature >= 200 { continue } - sensorName := sensor.SensorKey - if _, ok := systemStats.Temperatures[sensorName]; ok { - // if key already exists, append int to key - sensorName = sensorName + "_" + strconv.Itoa(i) - } // skip if not in whitelist or blacklist if !isValidSensor(sensorName, a.sensorConfig) { continue diff --git a/agent/sensors_test.go b/agent/sensors_test.go index 2a3ace60c..6229761f8 100644 --- a/agent/sensors_test.go +++ b/agent/sensors_test.go @@ -798,3 +798,51 @@ func TestUpdateTemperaturesSkipGpu(t *testing.T) { newAgent(false).updateTemperatures(stats) assert.Len(t, stats.Temperatures, 2) } + +func TestUpdateTemperaturesExcludedSensorKeepsNames(t *testing.T) { + originalGetSensorTemps := getSensorTemps + t.Cleanup(func() { + getSensorTemps = originalGetSensorTemps + }) + // two drives that report the same SensorKey, plus an unrelated sensor + getSensorTemps = func(ctx context.Context) ([]sensors.TemperatureStat, error) { + return []sensors.TemperatureStat{ + {SensorKey: "nvme_sensor_2", Temperature: 74.85}, + {SensorKey: "nvme_sensor_2", Temperature: 41}, + {SensorKey: "coretemp_core_0", Temperature: 55}, + }, nil + } + + newAgent := func(exclude string) *Agent { + config := map[string]struct{}{} + if exclude != "" { + config[exclude] = struct{}{} + } + return &Agent{ + systemInfo: system.Info{}, + sensorConfig: &SensorConfig{ + context: context.Background(), + timeout: 2 * time.Second, + sensors: config, + isBlacklist: exclude != "", + }, + } + } + + // unfiltered: the second duplicate is suffixed with its index + stats := &system.Stats{} + newAgent("").updateTemperatures(stats) + assert.Equal(t, map[string]float64{ + "nvme_sensor_2": 74.85, + "nvme_sensor_2_1": 41, + "coretemp_core_0": 55, + }, stats.Temperatures) + + // excluding the first duplicate keeps the second one's name + stats = &system.Stats{} + newAgent("nvme_sensor_2").updateTemperatures(stats) + assert.Equal(t, map[string]float64{ + "nvme_sensor_2_1": 41, + "coretemp_core_0": 55, + }, stats.Temperatures) +}