From 58bb87d3fc80975e3dcb57cd1c7984d66c1b616d Mon Sep 17 00:00:00 2001 From: samoz83 Date: Thu, 15 Jan 2026 17:49:07 +0000 Subject: [PATCH 1/3] fix(collector): add index label to hwmon metrics to distinguish devices On dual socket systems multiple hwmon devices can share the same chip_name. This adds an index label derived from the directory name to ensure uniqueness. --- pkg/collector/hwmon.go | 18 +++++++++++++----- pkg/collector/hwmon_test.go | 3 +++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/pkg/collector/hwmon.go b/pkg/collector/hwmon.go index f1ec9f09..a9f94ac5 100644 --- a/pkg/collector/hwmon.go +++ b/pkg/collector/hwmon.go @@ -39,6 +39,7 @@ type hwmon struct { sensors []hwmonSensor name string chipName string + index string } type hwmonSensor struct { @@ -63,23 +64,23 @@ func NewHwmonCollector(logger *slog.Logger) (Collector, error) { metricDesc["power_input"] = prometheus.NewDesc( prometheus.BuildFQName(Namespace, hwmonCollectorSubSystem, "power_current_watts"), - "Current Power consumption in watts", []string{"hostname", "sensor", "chip", "chip_name"}, nil, + "Current Power consumption in watts", []string{"hostname", "index", "sensor", "chip", "chip_name"}, nil, ) metricDesc["power_input_lowest"] = prometheus.NewDesc( prometheus.BuildFQName(Namespace, hwmonCollectorSubSystem, "power_min_watts"), - "Minimum Power consumption in watts", []string{"hostname", "sensor", "chip", "chip_name"}, nil, + "Minimum Power consumption in watts", []string{"hostname", "index", "sensor", "chip", "chip_name"}, nil, ) metricDesc["power_input_highest"] = prometheus.NewDesc( prometheus.BuildFQName(Namespace, hwmonCollectorSubSystem, "power_max_watts"), - "Maximum Power consumption in watts", []string{"hostname", "sensor", "chip", "chip_name"}, nil, + "Maximum Power consumption in watts", []string{"hostname", "index", "sensor", "chip", "chip_name"}, nil, ) metricDesc["power_average"] = prometheus.NewDesc( prometheus.BuildFQName(Namespace, hwmonCollectorSubSystem, "power_avg_watts"), - "Average Power consumption in watts", []string{"hostname", "sensor", "chip", "chip_name"}, nil, + "Average Power consumption in watts", []string{"hostname", "index", "sensor", "chip", "chip_name"}, nil, ) metricDesc["energy_input"] = prometheus.NewDesc( prometheus.BuildFQName(Namespace, hwmonCollectorSubSystem, "energy_current_joules"), - "Current Energy consumption in joules", []string{"hostname", "sensor", "chip", "chip_name"}, nil, + "Current Energy consumption in joules", []string{"hostname", "index", "sensor", "chip", "chip_name"}, nil, ) hwmonCollector := &hwmonCollector{ @@ -116,6 +117,7 @@ func (c *hwmonCollector) Update(ch chan<- prometheus.Metric) error { prometheus.GaugeValue, val/1000000.0, c.hostname, + mon.index, fmt.Sprintf("%s%d", sensor.sensorType, sensor.sensorNum), mon.name, mon.chipName, @@ -215,6 +217,12 @@ func getHwmon(dir string) (*hwmon, error) { hwmon := &hwmon{dir: dir, name: hwmonName, sensors: sensors} + // Extract index from directory name (e.g., "hwmon1" -> "1") + base := filepath.Base(dir) + if strings.HasPrefix(base, "hwmon") { + hwmon.index = strings.TrimPrefix(base, "hwmon") + } + hwmonChipName, err := hwmonHumanReadableChipName(dir) if err == nil { hwmon.chipName = hwmonChipName diff --git a/pkg/collector/hwmon_test.go b/pkg/collector/hwmon_test.go index c65cd7ae..e7678adf 100644 --- a/pkg/collector/hwmon_test.go +++ b/pkg/collector/hwmon_test.go @@ -90,6 +90,9 @@ func TestHwmonMetrics(t *testing.T) { gotValues[mon.name][sensor.sensorProperty][fmt.Sprintf("%s%d", sensor.sensorType, sensor.sensorNum)] = val } } + + // Verify index is extracted (should not be empty for hwmon devices) + assert.NotEmpty(t, mon.index, "Monitor index should not be empty") } assert.Equal(t, expectedHwmonValues, gotValues) From 67aa4b4117ae17f2acf44a9d30ed1d119071b031 Mon Sep 17 00:00:00 2001 From: samoz83 Date: Thu, 15 Jan 2026 23:19:54 +0000 Subject: [PATCH 2/3] modernise and simplify index extraction using strings.CutPrefix --- pkg/collector/hwmon.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg/collector/hwmon.go b/pkg/collector/hwmon.go index a9f94ac5..77ff9533 100644 --- a/pkg/collector/hwmon.go +++ b/pkg/collector/hwmon.go @@ -218,9 +218,8 @@ func getHwmon(dir string) (*hwmon, error) { hwmon := &hwmon{dir: dir, name: hwmonName, sensors: sensors} // Extract index from directory name (e.g., "hwmon1" -> "1") - base := filepath.Base(dir) - if strings.HasPrefix(base, "hwmon") { - hwmon.index = strings.TrimPrefix(base, "hwmon") + if index, ok := strings.CutPrefix(filepath.Base(dir), "hwmon"); ok { + hwmon.index = index } hwmonChipName, err := hwmonHumanReadableChipName(dir) From 58ffcbe4cc5b3f2d79ccf0ad173299f7a22e7833 Mon Sep 17 00:00:00 2001 From: Mahendra Paipuri Date: Sun, 18 Jan 2026 20:13:39 +0100 Subject: [PATCH 3/3] test: Update e2e test fixtures Signed-off-by: Mahendra Paipuri --- ...e2e-test-cgroupsv2-amd-ipmitool-output.txt | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/collector/testdata/output/exporter/e2e-test-cgroupsv2-amd-ipmitool-output.txt b/pkg/collector/testdata/output/exporter/e2e-test-cgroupsv2-amd-ipmitool-output.txt index 19888b2c..33d6720a 100644 --- a/pkg/collector/testdata/output/exporter/e2e-test-cgroupsv2-amd-ipmitool-output.txt +++ b/pkg/collector/testdata/output/exporter/e2e-test-cgroupsv2-amd-ipmitool-output.txt @@ -157,24 +157,24 @@ ceems_cpu_seconds_total{hostname="",mode="user"} 3018.54 # TYPE ceems_exporter_build_info gauge # HELP ceems_hwmon_energy_current_joules Current Energy consumption in joules # TYPE ceems_hwmon_energy_current_joules gauge -ceems_hwmon_energy_current_joules{chip="socket",chip_name="socket",hostname="",sensor="energy1"} 22323 -ceems_hwmon_energy_current_joules{chip="socket",chip_name="socket",hostname="",sensor="energy2"} 9509 +ceems_hwmon_energy_current_joules{chip="socket",chip_name="socket",hostname="",index="4",sensor="energy1"} 22323 +ceems_hwmon_energy_current_joules{chip="socket",chip_name="socket",hostname="",index="4",sensor="energy2"} 9509 # HELP ceems_hwmon_power_avg_watts Average Power consumption in watts # TYPE ceems_hwmon_power_avg_watts gauge -ceems_hwmon_power_avg_watts{chip="socket",chip_name="socket",hostname="",sensor="power1"} 234 -ceems_hwmon_power_avg_watts{chip="socket",chip_name="socket",hostname="",sensor="power2"} 120 +ceems_hwmon_power_avg_watts{chip="socket",chip_name="socket",hostname="",index="4",sensor="power1"} 234 +ceems_hwmon_power_avg_watts{chip="socket",chip_name="socket",hostname="",index="4",sensor="power2"} 120 # HELP ceems_hwmon_power_current_watts Current Power consumption in watts # TYPE ceems_hwmon_power_current_watts gauge -ceems_hwmon_power_current_watts{chip="socket",chip_name="socket",hostname="",sensor="power1"} 270 -ceems_hwmon_power_current_watts{chip="socket",chip_name="socket",hostname="",sensor="power2"} 156 +ceems_hwmon_power_current_watts{chip="socket",chip_name="socket",hostname="",index="4",sensor="power1"} 270 +ceems_hwmon_power_current_watts{chip="socket",chip_name="socket",hostname="",index="4",sensor="power2"} 156 # HELP ceems_hwmon_power_max_watts Maximum Power consumption in watts # TYPE ceems_hwmon_power_max_watts gauge -ceems_hwmon_power_max_watts{chip="socket",chip_name="socket",hostname="",sensor="power1"} 328 -ceems_hwmon_power_max_watts{chip="socket",chip_name="socket",hostname="",sensor="power2"} 190 +ceems_hwmon_power_max_watts{chip="socket",chip_name="socket",hostname="",index="4",sensor="power1"} 328 +ceems_hwmon_power_max_watts{chip="socket",chip_name="socket",hostname="",index="4",sensor="power2"} 190 # HELP ceems_hwmon_power_min_watts Minimum Power consumption in watts # TYPE ceems_hwmon_power_min_watts gauge -ceems_hwmon_power_min_watts{chip="socket",chip_name="socket",hostname="",sensor="power1"} 65 -ceems_hwmon_power_min_watts{chip="socket",chip_name="socket",hostname="",sensor="power2"} 46 +ceems_hwmon_power_min_watts{chip="socket",chip_name="socket",hostname="",index="4",sensor="power1"} 65 +ceems_hwmon_power_min_watts{chip="socket",chip_name="socket",hostname="",index="4",sensor="power2"} 46 # HELP ceems_ipmi_dcmi_power_avg_watts Average power consumption reported by DCMI in watts # TYPE ceems_ipmi_dcmi_power_avg_watts gauge ceems_ipmi_dcmi_power_avg_watts{hostname=""} 2567