From b53d91e04846975de7bee8bbe5613bf451e8f069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Sat, 31 Aug 2024 12:22:22 +0200 Subject: [PATCH] cpu_info: Extend processor information (#1597) --- README.md | 2 +- docs/collector.cpu_info.md | 34 +++++++- pkg/collector/cpu_info/cpu_info.go | 123 +++++++++++++++++++++++++---- tools/e2e-output.txt | 16 ++++ tools/end-to-end-test.ps1 | 2 +- tools/promtool.ps1 | 2 +- 6 files changed, 155 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 6426ff6e3..e21593710 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Name | Description | Enabled by default [cache](docs/collector.cache.md) | Cache metrics | [cpu](docs/collector.cpu.md) | CPU usage | ✓ [cpu_info](docs/collector.cpu_info.md) | CPU Information | -[cs](docs/collector.cs.md) | "Computer System" metrics (system properties, num cpus/total memory) | ✓ +[cs](docs/collector.cs.md) | "Computer System" metrics (system properties, num cpus/total memory) | [container](docs/collector.container.md) | Container metrics | [diskdrive](docs/collector.diskdrive.md) | Diskdrive metrics | [dfsr](docs/collector.dfsr.md) | DFSR metrics | diff --git a/docs/collector.cpu_info.md b/docs/collector.cpu_info.md index 52b3b4c42..dd21649e4 100644 --- a/docs/collector.cpu_info.md +++ b/docs/collector.cpu_info.md @@ -15,13 +15,39 @@ None ## Metrics -Name | Description | Type | Labels ------|-------------|------|------- -`windows_cpu_info` | Labelled CPU information | gauge | `architecture`, `device_id`, `description`, `family`, `l2_cache_size` `l3_cache_size`, `name` +| Name | Description | Type | Labels | +|--------------------------------------------|--------------------------------------|-------|--------------------------------------------------------------| +| `windows_cpu_info` | Labelled CPU information | gauge | `architecture`, `description`, `device_id`, `family`, `name` | +| `windows_cpu_info_core` | Number of cores per CPU | gauge | `device_id` | +| `windows_cpu_info_enabled_core` | Number of enabled cores per CPU | gauge | `device_id` | +| `windows_cpu_info_l2_cache_size` | Size of L2 cache per CPU | gauge | `device_id` | +| `windows_cpu_info_l3_cache_size` | Size of L3 cache per CPU | gauge | `device_id` | +| `windows_cpu_info_logical_processor` | Number of logical processors per CPU | gauge | `device_id` | +| `windows_cpu_info_thread` | Number of threads per CPU | gauge | `device_id` | ### Example metric ``` -windows_cpu_info{architecture="9",description="AMD64 Family 23 Model 49 Stepping 0",device_id="CPU0",family="107",l2_cache_size="32768",l3_cache_size="262144",name="AMD EPYC 7702P 64-Core Processor"} 1 +# HELP windows_cpu_info Labelled CPU information as provided by Win32_Processor +# TYPE windows_cpu_info gauge +windows_cpu_info{architecture="9",description="AMD64 Family 25 Model 33 Stepping 2",device_id="CPU0",family="107",name="AMD Ryzen 9 5900X 12-Core Processor"} 1 +# HELP windows_cpu_info_core Number of cores per CPU +# TYPE windows_cpu_info_core gauge +windows_cpu_info_core{device_id="CPU0"} 12 +# HELP windows_cpu_info_enabled_core Number of enabled cores per CPU +# TYPE windows_cpu_info_enabled_core gauge +windows_cpu_info_enabled_core{device_id="CPU0"} 12 +# HELP windows_cpu_info_l2_cache_size Size of L2 cache per CPU +# TYPE windows_cpu_info_l2_cache_size gauge +windows_cpu_info_l2_cache_size{device_id="CPU0"} 6144 +# HELP windows_cpu_info_l3_cache_size Size of L3 cache per CPU +# TYPE windows_cpu_info_l3_cache_size gauge +windows_cpu_info_l3_cache_size{device_id="CPU0"} 65536 +# HELP windows_cpu_info_logical_processor Number of logical processors per CPU +# TYPE windows_cpu_info_logical_processor gauge +windows_cpu_info_logical_processor{device_id="CPU0"} 24 +# HELP windows_cpu_info_thread Number of threads per CPU +# TYPE windows_cpu_info_thread gauge +windows_cpu_info_thread{device_id="CPU0"} 24 ``` The value of the metric is irrelevant, but the labels expose some useful information on the CPU installed in each socket. diff --git a/pkg/collector/cpu_info/cpu_info.go b/pkg/collector/cpu_info/cpu_info.go index 5de9dfb27..fb5f43a2f 100644 --- a/pkg/collector/cpu_info/cpu_info.go +++ b/pkg/collector/cpu_info/cpu_info.go @@ -17,8 +17,6 @@ import ( const ( Name = "cpu_info" - // If you are adding additional labels to the metric, make sure that they get added in here as well. See below for explanation. - win32ProcessorQuery = "SELECT Architecture, DeviceId, Description, Family, L2CacheSize, L3CacheSize, Name FROM Win32_Processor" ) type Config struct{} @@ -30,7 +28,14 @@ type Collector struct { config Config wmiClient *wmi.Client - cpuInfo *prometheus.Desc + + cpuInfo *prometheus.Desc + cpuCoreCount *prometheus.Desc + cpuEnabledCoreCount *prometheus.Desc + cpuLogicalProcessorsCount *prometheus.Desc + cpuThreadCount *prometheus.Desc + cpuL2CacheSize *prometheus.Desc + cpuL3CacheSize *prometheus.Desc } func New(config *Config) *Collector { @@ -75,24 +80,74 @@ func (c *Collector) Build(_ log.Logger, wmiClient *wmi.Client) error { "device_id", "description", "family", - "l2_cache_size", - "l3_cache_size", "name", }, nil, ) + c.cpuThreadCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "thread"), + "Number of threads per CPU", + []string{ + "device_id", + }, + nil, + ) + c.cpuCoreCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "core"), + "Number of cores per CPU", + []string{ + "device_id", + }, + nil, + ) + c.cpuEnabledCoreCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "enabled_core"), + "Number of enabled cores per CPU", + []string{ + "device_id", + }, + nil, + ) + c.cpuLogicalProcessorsCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "logical_processor"), + "Number of logical processors per CPU", + []string{ + "device_id", + }, + nil, + ) + c.cpuL2CacheSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "l2_cache_size"), + "Size of L2 cache per CPU", + []string{ + "device_id", + }, + nil, + ) + c.cpuL3CacheSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "l3_cache_size"), + "Size of L3 cache per CPU", + []string{ + "device_id", + }, + nil, + ) return nil } -type win32_Processor struct { - Architecture uint32 - DeviceID string - Description string - Family uint16 - L2CacheSize uint32 - L3CacheSize uint32 - Name string +type win32Processor struct { + Architecture uint32 + DeviceID string + Description string + Family uint16 + L2CacheSize uint32 + L3CacheSize uint32 + Name string + ThreadCount uint32 + NumberOfCores uint32 + NumberOfEnabledCore uint32 + NumberOfLogicalProcessors uint32 } // Collect sends the metric values for each metric @@ -107,11 +162,11 @@ func (c *Collector) Collect(_ *types.ScrapeContext, logger log.Logger, ch chan<- } func (c *Collector) collect(ch chan<- prometheus.Metric) error { - var dst []win32_Processor + var dst []win32Processor // We use a static query here because the provided methods in wmi.go all issue a SELECT *; // This results in the time-consuming LoadPercentage field being read which seems to measure each CPU // serially over a 1 second interval, so the scrape time is at least 1s * num_sockets - if err := c.wmiClient.Query(win32ProcessorQuery, &dst); err != nil { + if err := c.wmiClient.Query("SELECT Architecture, DeviceId, Description, Family, L2CacheSize, L3CacheSize, Name, ThreadCount, NumberOfCores, NumberOfEnabledCore, NumberOfLogicalProcessors FROM Win32_Processor", &dst); err != nil { return err } if len(dst) == 0 { @@ -128,10 +183,44 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error { strings.TrimRight(processor.DeviceID, " "), strings.TrimRight(processor.Description, " "), strconv.Itoa(int(processor.Family)), - strconv.Itoa(int(processor.L2CacheSize)), - strconv.Itoa(int(processor.L3CacheSize)), strings.TrimRight(processor.Name, " "), ) + ch <- prometheus.MustNewConstMetric( + c.cpuCoreCount, + prometheus.GaugeValue, + float64(processor.NumberOfCores), + strings.TrimRight(processor.DeviceID, " "), + ) + ch <- prometheus.MustNewConstMetric( + c.cpuEnabledCoreCount, + prometheus.GaugeValue, + float64(processor.NumberOfEnabledCore), + strings.TrimRight(processor.DeviceID, " "), + ) + ch <- prometheus.MustNewConstMetric( + c.cpuLogicalProcessorsCount, + prometheus.GaugeValue, + float64(processor.NumberOfLogicalProcessors), + strings.TrimRight(processor.DeviceID, " "), + ) + ch <- prometheus.MustNewConstMetric( + c.cpuThreadCount, + prometheus.GaugeValue, + float64(processor.ThreadCount), + strings.TrimRight(processor.DeviceID, " "), + ) + ch <- prometheus.MustNewConstMetric( + c.cpuL2CacheSize, + prometheus.GaugeValue, + float64(processor.L2CacheSize), + strings.TrimRight(processor.DeviceID, " "), + ) + ch <- prometheus.MustNewConstMetric( + c.cpuL3CacheSize, + prometheus.GaugeValue, + float64(processor.L3CacheSize), + strings.TrimRight(processor.DeviceID, " "), + ) } return nil diff --git a/tools/e2e-output.txt b/tools/e2e-output.txt index 5f7d6c784..084d0808b 100644 --- a/tools/e2e-output.txt +++ b/tools/e2e-output.txt @@ -11,6 +11,20 @@ test_alpha_total 42 # TYPE windows_cpu_dpcs_total counter # HELP windows_cpu_idle_break_events_total Total number of time processor was woken from idle # TYPE windows_cpu_idle_break_events_total counter +# HELP windows_cpu_info Labelled CPU information as provided by Win32_Processor +# TYPE windows_cpu_info gauge +# HELP windows_cpu_info_core Number of cores per CPU +# TYPE windows_cpu_info_core gauge +# HELP windows_cpu_info_enabled_core Number of enabled cores per CPU +# TYPE windows_cpu_info_enabled_core gauge +# HELP windows_cpu_info_l2_cache_size Size of L2 cache per CPU +# TYPE windows_cpu_info_l2_cache_size gauge +# HELP windows_cpu_info_l3_cache_size Size of L3 cache per CPU +# TYPE windows_cpu_info_l3_cache_size gauge +# HELP windows_cpu_info_logical_processor Number of logical processors per CPU +# TYPE windows_cpu_info_logical_processor gauge +# HELP windows_cpu_info_thread Number of threads per CPU +# TYPE windows_cpu_info_thread gauge # HELP windows_cpu_interrupts_total Total number of received and serviced hardware interrupts # TYPE windows_cpu_interrupts_total counter # HELP windows_cpu_parking_status Parking Status represents whether a processor is parked or not @@ -38,6 +52,7 @@ test_alpha_total 42 # HELP windows_exporter_collector_success windows_exporter: Whether the collector was successful. # TYPE windows_exporter_collector_success gauge windows_exporter_collector_success{collector="cpu"} 1 +windows_exporter_collector_success{collector="cpu_info"} 1 windows_exporter_collector_success{collector="cs"} 1 windows_exporter_collector_success{collector="logical_disk"} 1 windows_exporter_collector_success{collector="physical_disk"} 1 @@ -51,6 +66,7 @@ windows_exporter_collector_success{collector="textfile"} 1 # HELP windows_exporter_collector_timeout windows_exporter: Whether the collector timed out. # TYPE windows_exporter_collector_timeout gauge windows_exporter_collector_timeout{collector="cpu"} 0 +windows_exporter_collector_timeout{collector="cpu_info"} 0 windows_exporter_collector_timeout{collector="cs"} 0 windows_exporter_collector_timeout{collector="logical_disk"} 0 windows_exporter_collector_timeout{collector="physical_disk"} 0 diff --git a/tools/end-to-end-test.ps1 b/tools/end-to-end-test.ps1 index eea1156e0..d1597ff55 100644 --- a/tools/end-to-end-test.ps1 +++ b/tools/end-to-end-test.ps1 @@ -25,7 +25,7 @@ $skip_re = "^(go_|windows_exporter_build_info|windows_exporter_collector_duratio $exporter_proc = Start-Process ` -PassThru ` -FilePath ..\windows_exporter.exe ` - -ArgumentList "--log.level=debug --web.disable-exporter-metrics --collectors.enabled=[defaults],textfile,process,scheduled_task --collector.process.include=explorer.exe --collector.scheduled_task.include=.*WinSAT --collector.textfile.directories=$($textfile_dir)" ` + -ArgumentList "--log.level=debug --web.disable-exporter-metrics --collectors.enabled=[defaults],cpu_info,textfile,process,scheduled_task --collector.process.include=explorer.exe --collector.scheduled_task.include=.*WinSAT --collector.textfile.directories=$($textfile_dir)" ` -WindowStyle Hidden ` -RedirectStandardOutput "$($temp_dir)/windows_exporter.log" ` -RedirectStandardError "$($temp_dir)/windows_exporter_error.log" diff --git a/tools/promtool.ps1 b/tools/promtool.ps1 index 2ee8800cb..89d7ba2ff 100644 --- a/tools/promtool.ps1 +++ b/tools/promtool.ps1 @@ -93,7 +93,7 @@ $temp_dir = Join-Path $env:TEMP $(New-Guid) | ForEach-Object { mkdir $_ } $exporter_proc = Start-Process ` -PassThru ` -FilePath ..\windows_exporter.exe ` - -ArgumentList '--web.listen-address="127.0.0.1:9183" --log.level=debug' ` + -ArgumentList '--web.listen-address="127.0.0.1:9183" --log.level=debug --collectors.enabled=[defaults],cpu_info,textfile,process,scheduled_task'` -WindowStyle Hidden ` -RedirectStandardOutput "$($temp_dir)/windows_exporter.log" ` -RedirectStandardError "$($temp_dir)/windows_exporter_error.log"