diff --git a/README.md b/README.md index c761363de3..c9ff6ea4f2 100644 --- a/README.md +++ b/README.md @@ -183,6 +183,7 @@ Name | Description | OS ---------|-------------|---- buddyinfo | Exposes statistics of memory fragments as reported by /proc/buddyinfo. | Linux cgroups | A summary of the number of active and enabled cgroups | Linux +cpu\_vulnerabilities | Exposes CPU vulnerability information from sysfs. | Linux devstat | Exposes device statistics | Dragonfly, FreeBSD drbd | Exposes Distributed Replicated Block Device statistics (to version 8.4) | Linux ethtool | Exposes network interface information and network driver statistics equivalent to `ethtool`, `ethtool -S`, and `ethtool -i`. | Linux diff --git a/collector/cpu_vulnerabilities_linux.go b/collector/cpu_vulnerabilities_linux.go new file mode 100644 index 0000000000..3e93cad7e8 --- /dev/null +++ b/collector/cpu_vulnerabilities_linux.go @@ -0,0 +1,81 @@ +// Copyright 2023 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package collector + +import ( + "fmt" + + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/procfs/sysfs" +) + +const ( + cpuVulerabilitiesCollector = "cpu_vulnerabilities" +) + +var ( + vulnerabilityDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, cpuVulerabilitiesCollector, "info"), + "Details of each CPU vulnerability reported by sysfs. The value of the series is an int encoded state of the vulnerability. The same state is stored as a string in the label", + []string{"codename", "state"}, + nil, + ) + totalCountDesc = prometheus.NewDesc( + prometheus.BuildFQName(namespace, cpuVulerabilitiesCollector, "total"), + "Total number of reported vulnerabilities", + nil, + nil, + ) +) + +type cpuVulnerabilitiesCollector struct { + vulnerabilities map[string]*sysfs.Vulnerability + total float64 +} + +func init() { + registerCollector(cpuVulerabilitiesCollector, defaultDisabled, NewVulnerabilitySysfsCollector) +} + +func NewVulnerabilitySysfsCollector(logger log.Logger) (Collector, error) { + fs, err := sysfs.NewFS(*sysPath) + if err != nil { + return nil, fmt.Errorf("failed to open sysfs: %w", err) + } + + vulnerabilities, err := fs.CPUVulnerabilities() + if err != nil { + return nil, fmt.Errorf("failed to get vulnerabilities: %w", err) + } + + return &cpuVulnerabilitiesCollector{ + vulnerabilities: vulnerabilities, + total: float64(len(vulnerabilities)), // this assumes the number of cpu vulnerabilities doesn't change during the lifetime of the node_exporter process + }, nil +} + +func (v *cpuVulnerabilitiesCollector) Update(ch chan<- prometheus.Metric) error { + ch <- prometheus.MustNewConstMetric(totalCountDesc, prometheus.CounterValue, v.total) + for _, vulnerability := range v.vulnerabilities { + ch <- prometheus.MustNewConstMetric( + vulnerabilityDesc, + prometheus.GaugeValue, + float64(vulnerability.State), + vulnerability.CodeName, + sysfs.VulnerabilityHumanEncoding[vulnerability.State], + ) + } + return nil +} diff --git a/collector/fixtures/e2e-64k-page-output.txt b/collector/fixtures/e2e-64k-page-output.txt index 760b475e3c..d2ea6ec276 100644 --- a/collector/fixtures/e2e-64k-page-output.txt +++ b/collector/fixtures/e2e-64k-page-output.txt @@ -402,6 +402,16 @@ node_cpu_seconds_total{cpu="7",mode="softirq"} 0.31 node_cpu_seconds_total{cpu="7",mode="steal"} 0 node_cpu_seconds_total{cpu="7",mode="system"} 101.64 node_cpu_seconds_total{cpu="7",mode="user"} 290.98 +# HELP node_cpu_vulnerabilities_info Details of each CPU vulnerability reported by sysfs. The value of the series is an int encoded state of the vulnerability. The same state is stored as a string in the label +# TYPE node_cpu_vulnerabilities_info gauge +node_cpu_vulnerabilities_info{codename="itlb_multihit",state="not affected"} 0 +node_cpu_vulnerabilities_info{codename="mds",state="vulnerable"} 1 +node_cpu_vulnerabilities_info{codename="retbleed",state="mitigation"} 2 +node_cpu_vulnerabilities_info{codename="spectre_v1",state="mitigation"} 2 +node_cpu_vulnerabilities_info{codename="spectre_v2",state="mitigation"} 2 +# HELP node_cpu_vulnerabilities_total Total number of reported vulnerabilities +# TYPE node_cpu_vulnerabilities_total counter +node_cpu_vulnerabilities_total 5 # HELP node_disk_ata_rotation_rate_rpm ATA disk rotation rate in RPMs (0 for SSDs). # TYPE node_disk_ata_rotation_rate_rpm gauge node_disk_ata_rotation_rate_rpm{device="sda"} 7200 @@ -2887,6 +2897,7 @@ node_scrape_collector_success{collector="buddyinfo"} 1 node_scrape_collector_success{collector="cgroups"} 1 node_scrape_collector_success{collector="conntrack"} 1 node_scrape_collector_success{collector="cpu"} 1 +node_scrape_collector_success{collector="cpu_vulnerabilities"} 1 node_scrape_collector_success{collector="cpufreq"} 1 node_scrape_collector_success{collector="diskstats"} 1 node_scrape_collector_success{collector="dmi"} 1 diff --git a/collector/fixtures/e2e-output.txt b/collector/fixtures/e2e-output.txt index a8d5664963..ccf427c888 100644 --- a/collector/fixtures/e2e-output.txt +++ b/collector/fixtures/e2e-output.txt @@ -424,6 +424,16 @@ node_cpu_seconds_total{cpu="7",mode="softirq"} 0.31 node_cpu_seconds_total{cpu="7",mode="steal"} 0 node_cpu_seconds_total{cpu="7",mode="system"} 101.64 node_cpu_seconds_total{cpu="7",mode="user"} 290.98 +# HELP node_cpu_vulnerabilities_info Details of each CPU vulnerability reported by sysfs. The value of the series is an int encoded state of the vulnerability. The same state is stored as a string in the label +# TYPE node_cpu_vulnerabilities_info gauge +node_cpu_vulnerabilities_info{codename="itlb_multihit",state="not affected"} 0 +node_cpu_vulnerabilities_info{codename="mds",state="vulnerable"} 1 +node_cpu_vulnerabilities_info{codename="retbleed",state="mitigation"} 2 +node_cpu_vulnerabilities_info{codename="spectre_v1",state="mitigation"} 2 +node_cpu_vulnerabilities_info{codename="spectre_v2",state="mitigation"} 2 +# HELP node_cpu_vulnerabilities_total Total number of reported vulnerabilities +# TYPE node_cpu_vulnerabilities_total counter +node_cpu_vulnerabilities_total 5 # HELP node_disk_ata_rotation_rate_rpm ATA disk rotation rate in RPMs (0 for SSDs). # TYPE node_disk_ata_rotation_rate_rpm gauge node_disk_ata_rotation_rate_rpm{device="sda"} 7200 @@ -2909,6 +2919,7 @@ node_scrape_collector_success{collector="buddyinfo"} 1 node_scrape_collector_success{collector="cgroups"} 1 node_scrape_collector_success{collector="conntrack"} 1 node_scrape_collector_success{collector="cpu"} 1 +node_scrape_collector_success{collector="cpu_vulnerabilities"} 1 node_scrape_collector_success{collector="cpufreq"} 1 node_scrape_collector_success{collector="diskstats"} 1 node_scrape_collector_success{collector="dmi"} 1 diff --git a/collector/fixtures/sys.ttar b/collector/fixtures/sys.ttar index 73e38e3cbc..ee152dfa3c 100644 --- a/collector/fixtures/sys.ttar +++ b/collector/fixtures/sys.ttar @@ -3555,6 +3555,34 @@ Lines: 1 0-3 Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: sys/devices/system/cpu/vulnerabilities +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/system/cpu/vulnerabilities/itlb_multihit +Lines: 1 +Not affected +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/system/cpu/vulnerabilities/mds +Lines: 1 +Vulnerable +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/system/cpu/vulnerabilities/retbleed +Lines: 1 +Mitigation: untrained return thunk; SMT enabled with STIBP protection +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/system/cpu/vulnerabilities/spectre_v1 +Lines: 1 +Mitigation: usercopy/swapgs barriers and __user pointer sanitization +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: sys/devices/system/cpu/vulnerabilities/spectre_v2 +Lines: 1 +Mitigation: Retpolines, IBPB: conditional, STIBP: always-on, RSB filling, PBRSB-eIBRS: Not affected +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: sys/devices/system/edac Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/end-to-end-test.sh b/end-to-end-test.sh index 75559e9c3b..c8dadc91b9 100755 --- a/end-to-end-test.sh +++ b/end-to-end-test.sh @@ -12,6 +12,7 @@ enabled_collectors=$(cat << COLLECTORS conntrack cpu cpufreq + cpu_vulnerabilities diskstats dmi drbd diff --git a/go.mod b/go.mod index c6651a60f2..05a8b8594b 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/prometheus/client_model v0.4.0 github.com/prometheus/common v0.44.0 github.com/prometheus/exporter-toolkit v0.10.0 - github.com/prometheus/procfs v0.10.1 + github.com/prometheus/procfs v0.11.0 github.com/safchain/ethtool v0.3.0 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 golang.org/x/sys v0.9.0 diff --git a/go.sum b/go.sum index 28f5de9d71..9dfdf97c2b 100644 --- a/go.sum +++ b/go.sum @@ -84,8 +84,8 @@ github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdO github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/exporter-toolkit v0.10.0 h1:yOAzZTi4M22ZzVxD+fhy1URTuNRj/36uQJJ5S8IPza8= github.com/prometheus/exporter-toolkit v0.10.0/go.mod h1:+sVFzuvV5JDyw+Ih6p3zFxZNVnKQa3x5qPmDSiPu4ZY= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prometheus/procfs v0.11.0 h1:5EAgkfkMl659uZPbe9AS2N68a7Cc1TJbPEuGzFuRbyk= +github.com/prometheus/procfs v0.11.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0= github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs=