Skip to content

Commit 2c56ef9

Browse files
committed
collector/cpu: Support CPU online status
Blocked by: prometheus/procfs#644. Signed-off-by: Pranshu Srivastava <[email protected]>
1 parent 40b32e6 commit 2c56ef9

File tree

4 files changed

+58
-15
lines changed

4 files changed

+58
-15
lines changed

collector/cpu_linux.go

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package collector
1818

1919
import (
20+
"errors"
2021
"fmt"
2122
"os"
2223
"path/filepath"
@@ -29,13 +30,14 @@ import (
2930
"github.com/go-kit/log"
3031
"github.com/go-kit/log/level"
3132
"github.com/prometheus/client_golang/prometheus"
32-
"github.com/prometheus/procfs"
33-
"github.com/prometheus/procfs/sysfs"
33+
"github.com/rexagod/procfs"
34+
"github.com/rexagod/procfs/sysfs"
3435
"golang.org/x/exp/maps"
3536
)
3637

3738
type cpuCollector struct {
38-
fs procfs.FS
39+
procfs procfs.FS
40+
sysfs sysfs.FS
3941
cpu *prometheus.Desc
4042
cpuInfo *prometheus.Desc
4143
cpuFrequencyHz *prometheus.Desc
@@ -45,6 +47,7 @@ type cpuCollector struct {
4547
cpuCoreThrottle *prometheus.Desc
4648
cpuPackageThrottle *prometheus.Desc
4749
cpuIsolated *prometheus.Desc
50+
cpuOnline *prometheus.Desc
4851
logger log.Logger
4952
cpuStats map[int64]procfs.CPUStat
5053
cpuStatsMutex sync.Mutex
@@ -71,17 +74,17 @@ func init() {
7174

7275
// NewCPUCollector returns a new Collector exposing kernel/system statistics.
7376
func NewCPUCollector(logger log.Logger) (Collector, error) {
74-
fs, err := procfs.NewFS(*procPath)
77+
pfs, err := procfs.NewFS(*procPath)
7578
if err != nil {
7679
return nil, fmt.Errorf("failed to open procfs: %w", err)
7780
}
7881

79-
sysfs, err := sysfs.NewFS(*sysPath)
82+
sfs, err := sysfs.NewFS(*sysPath)
8083
if err != nil {
8184
return nil, fmt.Errorf("failed to open sysfs: %w", err)
8285
}
8386

84-
isolcpus, err := sysfs.IsolatedCPUs()
87+
isolcpus, err := sfs.IsolatedCPUs()
8588
if err != nil {
8689
if !os.IsNotExist(err) {
8790
return nil, fmt.Errorf("Unable to get isolated cpus: %w", err)
@@ -90,8 +93,9 @@ func NewCPUCollector(logger log.Logger) (Collector, error) {
9093
}
9194

9295
c := &cpuCollector{
93-
fs: fs,
94-
cpu: nodeCPUSecondsDesc,
96+
procfs: pfs,
97+
sysfs: sfs,
98+
cpu: nodeCPUSecondsDesc,
9599
cpuInfo: prometheus.NewDesc(
96100
prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "info"),
97101
"CPU information from /proc/cpuinfo.",
@@ -132,6 +136,11 @@ func NewCPUCollector(logger log.Logger) (Collector, error) {
132136
"Whether each core is isolated, information from /sys/devices/system/cpu/isolated.",
133137
[]string{"cpu"}, nil,
134138
),
139+
cpuOnline: prometheus.NewDesc(
140+
prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "online"),
141+
"CPUs that are online and being scheduled.",
142+
[]string{"cpu"}, nil,
143+
),
135144
logger: logger,
136145
isolatedCpus: isolcpus,
137146
cpuStats: make(map[int64]procfs.CPUStat),
@@ -178,12 +187,21 @@ func (c *cpuCollector) Update(ch chan<- prometheus.Metric) error {
178187
if c.isolatedCpus != nil {
179188
c.updateIsolated(ch)
180189
}
181-
return c.updateThermalThrottle(ch)
190+
err := c.updateThermalThrottle(ch)
191+
if err != nil {
192+
return err
193+
}
194+
err = c.updateOnline(ch)
195+
if err != nil {
196+
return err
197+
}
198+
199+
return nil
182200
}
183201

184202
// updateInfo reads /proc/cpuinfo
185203
func (c *cpuCollector) updateInfo(ch chan<- prometheus.Metric) error {
186-
info, err := c.fs.CPUInfo()
204+
info, err := c.procfs.CPUInfo()
187205
if err != nil {
188206
return err
189207
}
@@ -334,9 +352,31 @@ func (c *cpuCollector) updateIsolated(ch chan<- prometheus.Metric) {
334352
}
335353
}
336354

355+
// updateOnline reads /sys/devices/system/cpu/cpu*/online through sysfs and exports online status metrics.
356+
func (c *cpuCollector) updateOnline(ch chan<- prometheus.Metric) error {
357+
cpus, err := c.sysfs.CPUs()
358+
if err != nil {
359+
return err
360+
}
361+
// No-op if the system does not support CPU online stats.
362+
cpu0 := cpus[0]
363+
if _, err := cpu0.Online(); err != nil && errors.Is(err, os.ErrNotExist) {
364+
return nil
365+
}
366+
for _, cpu := range cpus {
367+
setOnline := float64(0)
368+
if online, _ := cpu.Online(); online {
369+
setOnline = 1
370+
}
371+
ch <- prometheus.MustNewConstMetric(c.cpuOnline, prometheus.GaugeValue, setOnline, cpu.Number())
372+
}
373+
374+
return nil
375+
}
376+
337377
// updateStat reads /proc/stat through procfs and exports CPU-related metrics.
338378
func (c *cpuCollector) updateStat(ch chan<- prometheus.Metric) error {
339-
stats, err := c.fs.Stat()
379+
stats, err := c.procfs.Stat()
340380
if err != nil {
341381
return err
342382
}

collector/cpu_linux_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121
"testing"
2222

2323
"github.com/go-kit/log"
24-
"github.com/prometheus/procfs"
24+
"github.com/rexagod/procfs"
2525
)
2626

2727
func copyStats(d, s map[int64]procfs.CPUStat) {

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ require (
2727
github.com/prometheus/common v0.53.0
2828
github.com/prometheus/exporter-toolkit v0.11.0
2929
github.com/prometheus/procfs v0.14.0
30+
github.com/rexagod/procfs v0.0.0-00010101000000-000000000000
3031
github.com/safchain/ethtool v0.3.0
3132
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f
32-
golang.org/x/sys v0.19.0
33+
golang.org/x/sys v0.20.0
3334
howett.net/plist v1.0.1
3435
)
3536

@@ -59,3 +60,5 @@ require (
5960
google.golang.org/protobuf v1.33.0 // indirect
6061
gopkg.in/yaml.v2 v2.4.0 // indirect
6162
)
63+
64+
replace github.com/rexagod/procfs => ../procfs // https://github.com/prometheus/procfs/pull/644

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
116116
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
117117
golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
118118
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
119-
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
120-
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
119+
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
120+
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
121121
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
122122
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
123123
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=

0 commit comments

Comments
 (0)