diff --git a/docs/user/metrics.md b/docs/user/metrics.md index 09fdfbffe2..6eea912289 100644 --- a/docs/user/metrics.md +++ b/docs/user/metrics.md @@ -81,6 +81,8 @@ These metrics provide energy and power information at the node level. - `model_name` - `physical_id` - `core_id` +- **Constant Labels**: + - `node_name` #### kepler_node_cpu_joules_total diff --git a/hack/gen-metric-docs/main.go b/hack/gen-metric-docs/main.go index 444ae20824..0fe0f44728 100644 --- a/hack/gen-metric-docs/main.go +++ b/hack/gen-metric-docs/main.go @@ -350,7 +350,7 @@ func main() { fmt.Println("Created power collector") buildInfoCollector := collector.NewKeplerBuildInfoCollector() fmt.Println("Created build info collector") - cpuInfoCollector, err := collector.NewCPUInfoCollector("/proc") + cpuInfoCollector, err := collector.NewCPUInfoCollector("/proc", "test-node") if err != nil { fmt.Printf("Warning: Could not create CPU info collector: %v\n", err) } else { diff --git a/internal/exporter/prometheus/collector/cpuinfo.go b/internal/exporter/prometheus/collector/cpuinfo.go index 6c71d154fe..32f1f24c00 100644 --- a/internal/exporter/prometheus/collector/cpuinfo.go +++ b/internal/exporter/prometheus/collector/cpuinfo.go @@ -41,23 +41,23 @@ type cpuInfoCollector struct { } // NewCPUInfoCollector creates a CPUInfoCollector using a procfs mount path. -func NewCPUInfoCollector(procPath string) (*cpuInfoCollector, error) { +func NewCPUInfoCollector(procPath, nodeName string) (*cpuInfoCollector, error) { fs, err := newProcFS(procPath) if err != nil { return nil, fmt.Errorf("creating procfs failed: %w", err) } - return newCPUInfoCollectorWithFS(fs), nil + return newCPUInfoCollectorWithFS(fs, nodeName), nil } // newCPUInfoCollectorWithFS injects a procFS interface -func newCPUInfoCollectorWithFS(fs procFS) *cpuInfoCollector { +func newCPUInfoCollectorWithFS(fs procFS, nodeName string) *cpuInfoCollector { return &cpuInfoCollector{ fs: fs, desc: prom.NewDesc( prom.BuildFQName(keplerNS, "node", "cpu_info"), "CPU information from procfs", []string{"processor", "vendor_id", "model_name", "physical_id", "core_id"}, - nil, + prom.Labels{nodeNameLabel: nodeName}, ), } } diff --git a/internal/exporter/prometheus/collector/cpuinfo_test.go b/internal/exporter/prometheus/collector/cpuinfo_test.go index 258e45235c..12ea6e7c9c 100644 --- a/internal/exporter/prometheus/collector/cpuinfo_test.go +++ b/internal/exporter/prometheus/collector/cpuinfo_test.go @@ -50,13 +50,14 @@ func expectedLabels() map[string]string { "model_name": "", "physical_id": "", "core_id": "", + "node_name": "", } } // TestNewCPUInfoCollector tests the creation of a new CPUInfoCollector. func TestNewCPUInfoCollector(t *testing.T) { // Test successful creation with a mock procfs - collector, err := NewCPUInfoCollector("/proc") + collector, err := NewCPUInfoCollector("/proc", "test-node") assert.NoError(t, err) assert.NotNil(t, collector) assert.NotNil(t, collector.fs) @@ -70,12 +71,13 @@ func TestNewCPUInfoCollectorWithFS(t *testing.T) { return sampleCPUInfo(), nil }, } - collector := newCPUInfoCollectorWithFS(mockFS) + collector := newCPUInfoCollectorWithFS(mockFS, "test-node") assert.NotNil(t, collector) assert.Equal(t, mockFS, collector.fs) assert.NotNil(t, collector.desc) assert.Contains(t, collector.desc.String(), "kepler_node_cpu_info") assert.Contains(t, collector.desc.String(), "variableLabels: {processor,vendor_id,model_name,physical_id,core_id}") + assert.Contains(t, collector.desc.String(), `node_name="test-node"`) } // TestCPUInfoCollector_Describe tests the Describe method. @@ -85,7 +87,7 @@ func TestCPUInfoCollector_Describe(t *testing.T) { return sampleCPUInfo(), nil }, } - collector := newCPUInfoCollectorWithFS(mockFS) + collector := newCPUInfoCollectorWithFS(mockFS, "test-node") ch := make(chan *prometheus.Desc, 1) collector.Describe(ch) @@ -102,7 +104,7 @@ func TestCPUInfoCollector_Collect_Success(t *testing.T) { return sampleCPUInfo(), nil }, } - collector := newCPUInfoCollectorWithFS(mockFS) + collector := newCPUInfoCollectorWithFS(mockFS, "test-node") ch := make(chan prometheus.Metric, 10) collector.Collect(ch) @@ -140,7 +142,7 @@ func TestCPUInfoCollector_Collect_Error(t *testing.T) { return nil, errors.New("failed to read CPU info") }, } - collector := newCPUInfoCollectorWithFS(mockFS) + collector := newCPUInfoCollectorWithFS(mockFS, "test-node") ch := make(chan prometheus.Metric, 10) collector.Collect(ch) @@ -161,7 +163,7 @@ func TestCPUInfoCollector_Collect_Concurrency(t *testing.T) { return sampleCPUInfo(), nil }, } - collector := newCPUInfoCollectorWithFS(mockFS) + collector := newCPUInfoCollectorWithFS(mockFS, "test-node") const numGoroutines = 10 var wg sync.WaitGroup diff --git a/internal/exporter/prometheus/prometheus.go b/internal/exporter/prometheus/prometheus.go index d64dc5c746..f605131f14 100644 --- a/internal/exporter/prometheus/prometheus.go +++ b/internal/exporter/prometheus/prometheus.go @@ -156,7 +156,7 @@ func CreateCollectors(pm Monitor, applyOpts ...OptionFn) (map[string]prom.Collec "build_info": collector.NewKeplerBuildInfoCollector(), "power": collector.NewPowerCollector(pm, opts.nodeName, opts.logger, opts.metricsLevel), } - cpuInfoCollector, err := collector.NewCPUInfoCollector(opts.procfs) + cpuInfoCollector, err := collector.NewCPUInfoCollector(opts.procfs, opts.nodeName) if err != nil { return nil, err }