Skip to content

Commit

Permalink
collector/cpu: Support CPU online status
Browse files Browse the repository at this point in the history
Blocked by: prometheus/procfs#644.

Signed-off-by: Pranshu Srivastava <rexagod@gmail.com>
  • Loading branch information
rexagod committed May 30, 2024
1 parent 40b32e6 commit 2c56ef9
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 15 deletions.
62 changes: 51 additions & 11 deletions collector/cpu_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package collector

import (
"errors"
"fmt"
"os"
"path/filepath"
Expand All @@ -29,13 +30,14 @@ import (
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/procfs"
"github.com/prometheus/procfs/sysfs"
"github.com/rexagod/procfs"
"github.com/rexagod/procfs/sysfs"
"golang.org/x/exp/maps"
)

type cpuCollector struct {
fs procfs.FS
procfs procfs.FS
sysfs sysfs.FS
cpu *prometheus.Desc
cpuInfo *prometheus.Desc
cpuFrequencyHz *prometheus.Desc
Expand All @@ -45,6 +47,7 @@ type cpuCollector struct {
cpuCoreThrottle *prometheus.Desc
cpuPackageThrottle *prometheus.Desc
cpuIsolated *prometheus.Desc
cpuOnline *prometheus.Desc
logger log.Logger
cpuStats map[int64]procfs.CPUStat
cpuStatsMutex sync.Mutex
Expand All @@ -71,17 +74,17 @@ func init() {

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

sysfs, err := sysfs.NewFS(*sysPath)
sfs, err := sysfs.NewFS(*sysPath)
if err != nil {
return nil, fmt.Errorf("failed to open sysfs: %w", err)
}

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

c := &cpuCollector{
fs: fs,
cpu: nodeCPUSecondsDesc,
procfs: pfs,
sysfs: sfs,
cpu: nodeCPUSecondsDesc,
cpuInfo: prometheus.NewDesc(
prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "info"),
"CPU information from /proc/cpuinfo.",
Expand Down Expand Up @@ -132,6 +136,11 @@ func NewCPUCollector(logger log.Logger) (Collector, error) {
"Whether each core is isolated, information from /sys/devices/system/cpu/isolated.",
[]string{"cpu"}, nil,
),
cpuOnline: prometheus.NewDesc(
prometheus.BuildFQName(namespace, cpuCollectorSubsystem, "online"),
"CPUs that are online and being scheduled.",
[]string{"cpu"}, nil,
),
logger: logger,
isolatedCpus: isolcpus,
cpuStats: make(map[int64]procfs.CPUStat),
Expand Down Expand Up @@ -178,12 +187,21 @@ func (c *cpuCollector) Update(ch chan<- prometheus.Metric) error {
if c.isolatedCpus != nil {
c.updateIsolated(ch)
}
return c.updateThermalThrottle(ch)
err := c.updateThermalThrottle(ch)
if err != nil {
return err
}
err = c.updateOnline(ch)
if err != nil {
return err
}

return nil
}

// updateInfo reads /proc/cpuinfo
func (c *cpuCollector) updateInfo(ch chan<- prometheus.Metric) error {
info, err := c.fs.CPUInfo()
info, err := c.procfs.CPUInfo()
if err != nil {
return err
}
Expand Down Expand Up @@ -334,9 +352,31 @@ func (c *cpuCollector) updateIsolated(ch chan<- prometheus.Metric) {
}
}

// updateOnline reads /sys/devices/system/cpu/cpu*/online through sysfs and exports online status metrics.
func (c *cpuCollector) updateOnline(ch chan<- prometheus.Metric) error {
cpus, err := c.sysfs.CPUs()
if err != nil {
return err
}
// No-op if the system does not support CPU online stats.
cpu0 := cpus[0]
if _, err := cpu0.Online(); err != nil && errors.Is(err, os.ErrNotExist) {
return nil
}
for _, cpu := range cpus {
setOnline := float64(0)
if online, _ := cpu.Online(); online {
setOnline = 1
}
ch <- prometheus.MustNewConstMetric(c.cpuOnline, prometheus.GaugeValue, setOnline, cpu.Number())
}

return nil
}

// updateStat reads /proc/stat through procfs and exports CPU-related metrics.
func (c *cpuCollector) updateStat(ch chan<- prometheus.Metric) error {
stats, err := c.fs.Stat()
stats, err := c.procfs.Stat()
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion collector/cpu_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"testing"

"github.com/go-kit/log"
"github.com/prometheus/procfs"
"github.com/rexagod/procfs"
)

func copyStats(d, s map[int64]procfs.CPUStat) {
Expand Down
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ require (
github.com/prometheus/common v0.53.0
github.com/prometheus/exporter-toolkit v0.11.0
github.com/prometheus/procfs v0.14.0
github.com/rexagod/procfs v0.0.0-00010101000000-000000000000
github.com/safchain/ethtool v0.3.0
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f
golang.org/x/sys v0.19.0
golang.org/x/sys v0.20.0
howett.net/plist v1.0.1
)

Expand Down Expand Up @@ -59,3 +60,5 @@ require (
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

replace github.com/rexagod/procfs => ../procfs // https://github.com/prometheus/procfs/pull/644
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
Expand Down

0 comments on commit 2c56ef9

Please sign in to comment.