mirror of
https://github.com/prometheus/node_exporter.git
synced 2024-11-09 23:24:09 -08:00
Scrape cooling_device state
Signed-off-by: Alex Schmitz <alex.schmitz@gmail.com>
This commit is contained in:
parent
d3478a207e
commit
664025d60c
|
@ -24,6 +24,7 @@
|
||||||
* [BUGFIX] Fix netdev nil reference on Darwin #1414
|
* [BUGFIX] Fix netdev nil reference on Darwin #1414
|
||||||
* [BUGFIX] Strip path.rootfs from mountpoint labels #1421
|
* [BUGFIX] Strip path.rootfs from mountpoint labels #1421
|
||||||
* [FEATURE] Add new thermal_zone collector #1425
|
* [FEATURE] Add new thermal_zone collector #1425
|
||||||
|
* [FEATURE] Add new cooling_device metrics to thermal zone collector #1445
|
||||||
|
|
||||||
## 0.18.1 / 2019-06-04
|
## 0.18.1 / 2019-06-04
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ schedstat | Exposes task scheduler statistics from `/proc/schedstat`. | Linux
|
||||||
sockstat | Exposes various statistics from `/proc/net/sockstat`. | Linux
|
sockstat | Exposes various statistics from `/proc/net/sockstat`. | Linux
|
||||||
stat | Exposes various statistics from `/proc/stat`. This includes boot time, forks and interrupts. | Linux
|
stat | Exposes various statistics from `/proc/stat`. This includes boot time, forks and interrupts. | Linux
|
||||||
textfile | Exposes statistics read from local disk. The `--collector.textfile.directory` flag must be set. | _any_
|
textfile | Exposes statistics read from local disk. The `--collector.textfile.directory` flag must be set. | _any_
|
||||||
|
thermal\_zone | Exposes thermal zone & cooling device statistics from `/sys/class/thermal`. | Linux
|
||||||
time | Exposes the current system time. | _any_
|
time | Exposes the current system time. | _any_
|
||||||
timex | Exposes selected adjtimex(2) system call stats. | Linux
|
timex | Exposes selected adjtimex(2) system call stats. | Linux
|
||||||
uname | Exposes system information as provided by the uname system call. | Darwin, FreeBSD, Linux, OpenBSD
|
uname | Exposes system information as provided by the uname system call. | Darwin, FreeBSD, Linux, OpenBSD
|
||||||
|
|
|
@ -178,6 +178,12 @@ node_buddyinfo_blocks{node="0",size="9",zone="Normal"} 0
|
||||||
# HELP node_context_switches_total Total number of context switches.
|
# HELP node_context_switches_total Total number of context switches.
|
||||||
# TYPE node_context_switches_total counter
|
# TYPE node_context_switches_total counter
|
||||||
node_context_switches_total 3.8014093e+07
|
node_context_switches_total 3.8014093e+07
|
||||||
|
# HELP node_cooling_device_cur_state Current throttle state of the cooling device
|
||||||
|
# TYPE node_cooling_device_cur_state gauge
|
||||||
|
node_cooling_device_cur_state{name="0",type="Processor"} 0
|
||||||
|
# HELP node_cooling_device_max_state Maximum throttle state of the cooling device
|
||||||
|
# TYPE node_cooling_device_max_state gauge
|
||||||
|
node_cooling_device_max_state{name="0",type="Processor"} 3
|
||||||
# HELP node_cpu_core_throttles_total Number of times this cpu core has been throttled.
|
# HELP node_cpu_core_throttles_total Number of times this cpu core has been throttled.
|
||||||
# TYPE node_cpu_core_throttles_total counter
|
# TYPE node_cpu_core_throttles_total counter
|
||||||
node_cpu_core_throttles_total{core="0",package="0"} 5
|
node_cpu_core_throttles_total{core="0",package="0"} 5
|
||||||
|
|
|
@ -178,6 +178,12 @@ node_buddyinfo_blocks{node="0",size="9",zone="Normal"} 0
|
||||||
# HELP node_context_switches_total Total number of context switches.
|
# HELP node_context_switches_total Total number of context switches.
|
||||||
# TYPE node_context_switches_total counter
|
# TYPE node_context_switches_total counter
|
||||||
node_context_switches_total 3.8014093e+07
|
node_context_switches_total 3.8014093e+07
|
||||||
|
# HELP node_cooling_device_cur_state Current throttle state of the cooling device
|
||||||
|
# TYPE node_cooling_device_cur_state gauge
|
||||||
|
node_cooling_device_cur_state{name="0",type="Processor"} 0
|
||||||
|
# HELP node_cooling_device_max_state Maximum throttle state of the cooling device
|
||||||
|
# TYPE node_cooling_device_max_state gauge
|
||||||
|
node_cooling_device_max_state{name="0",type="Processor"} 3
|
||||||
# HELP node_cpu_core_throttles_total Number of times this cpu core has been throttled.
|
# HELP node_cpu_core_throttles_total Number of times this cpu core has been throttled.
|
||||||
# TYPE node_cpu_core_throttles_total counter
|
# TYPE node_cpu_core_throttles_total counter
|
||||||
node_cpu_core_throttles_total{core="0",package="0"} 5
|
node_cpu_core_throttles_total{core="0",package="0"} 5
|
||||||
|
|
|
@ -926,6 +926,9 @@ Mode: 755
|
||||||
Path: sys/class/thermal/thermal_zone0
|
Path: sys/class/thermal/thermal_zone0
|
||||||
SymlinkTo: ../../devices/virtual/thermal/thermal_zone0
|
SymlinkTo: ../../devices/virtual/thermal/thermal_zone0
|
||||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Path: sys/class/thermal/cooling_device0
|
||||||
|
SymlinkTo: ../../devices/virtual/thermal/cooling_device0
|
||||||
|
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Directory: sys/devices
|
Directory: sys/devices
|
||||||
Mode: 755
|
Mode: 755
|
||||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -2472,6 +2475,24 @@ Mode: 755
|
||||||
Directory: sys/devices/virtual/thermal
|
Directory: sys/devices/virtual/thermal
|
||||||
Mode: 755
|
Mode: 755
|
||||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Directory: sys/devices/virtual/thermal/cooling_device0
|
||||||
|
Mode: 755
|
||||||
|
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Path: sys/devices/virtual/thermal/cooling_device0/cur_state
|
||||||
|
Lines: 1
|
||||||
|
0
|
||||||
|
Mode: 644
|
||||||
|
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Path: sys/devices/virtual/thermal/cooling_device0/max_state
|
||||||
|
Lines: 1
|
||||||
|
3
|
||||||
|
Mode: 644
|
||||||
|
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
Path: sys/devices/virtual/thermal/cooling_device0/type
|
||||||
|
Lines: 1
|
||||||
|
Processor
|
||||||
|
Mode: 644
|
||||||
|
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Directory: sys/devices/virtual/thermal/thermal_zone0
|
Directory: sys/devices/virtual/thermal/thermal_zone0
|
||||||
Mode: 755
|
Mode: 755
|
||||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -22,9 +22,14 @@ import (
|
||||||
"github.com/prometheus/procfs/sysfs"
|
"github.com/prometheus/procfs/sysfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const coolingDevice = "cooling_device"
|
||||||
|
const thermalZone = "thermal_zone"
|
||||||
|
|
||||||
type thermalZoneCollector struct {
|
type thermalZoneCollector struct {
|
||||||
fs sysfs.FS
|
fs sysfs.FS
|
||||||
zoneTemp *prometheus.Desc
|
coolingDeviceCurState *prometheus.Desc
|
||||||
|
coolingDeviceMaxState *prometheus.Desc
|
||||||
|
zoneTemp *prometheus.Desc
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -41,10 +46,20 @@ func NewThermalZoneCollector() (Collector, error) {
|
||||||
return &thermalZoneCollector{
|
return &thermalZoneCollector{
|
||||||
fs: fs,
|
fs: fs,
|
||||||
zoneTemp: prometheus.NewDesc(
|
zoneTemp: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "thermal_zone", "temp"),
|
prometheus.BuildFQName(namespace, thermalZone, "temp"),
|
||||||
"Zone temperature in Celsius",
|
"Zone temperature in Celsius",
|
||||||
[]string{"zone", "type"}, nil,
|
[]string{"zone", "type"}, nil,
|
||||||
),
|
),
|
||||||
|
coolingDeviceCurState: prometheus.NewDesc(
|
||||||
|
prometheus.BuildFQName(namespace, coolingDevice, "cur_state"),
|
||||||
|
"Current throttle state of the cooling device",
|
||||||
|
[]string{"name", "type"}, nil,
|
||||||
|
),
|
||||||
|
coolingDeviceMaxState: prometheus.NewDesc(
|
||||||
|
prometheus.BuildFQName(namespace, coolingDevice, "max_state"),
|
||||||
|
"Maximum throttle state of the cooling device",
|
||||||
|
[]string{"name", "type"}, nil,
|
||||||
|
),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,5 +79,28 @@ func (c *thermalZoneCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
coolingDevices, err := c.fs.ClassCoolingDeviceStats()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, stats := range coolingDevices {
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.coolingDeviceCurState,
|
||||||
|
prometheus.GaugeValue,
|
||||||
|
float64(stats.CurState),
|
||||||
|
stats.Name,
|
||||||
|
stats.Type,
|
||||||
|
)
|
||||||
|
|
||||||
|
ch <- prometheus.MustNewConstMetric(
|
||||||
|
c.coolingDeviceMaxState,
|
||||||
|
prometheus.GaugeValue,
|
||||||
|
float64(stats.MaxState),
|
||||||
|
stats.Name,
|
||||||
|
stats.Type,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
85
vendor/github.com/prometheus/procfs/arp.go
generated
vendored
Normal file
85
vendor/github.com/prometheus/procfs/arp.go
generated
vendored
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
// Copyright 2019 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 procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ARPEntry contains a single row of the columnar data represented in
|
||||||
|
// /proc/net/arp.
|
||||||
|
type ARPEntry struct {
|
||||||
|
// IP address
|
||||||
|
IPAddr net.IP
|
||||||
|
// MAC address
|
||||||
|
HWAddr net.HardwareAddr
|
||||||
|
// Name of the device
|
||||||
|
Device string
|
||||||
|
}
|
||||||
|
|
||||||
|
// GatherARPEntries retrieves all the ARP entries, parse the relevant columns,
|
||||||
|
// and then return a slice of ARPEntry's.
|
||||||
|
func (fs FS) GatherARPEntries() ([]ARPEntry, error) {
|
||||||
|
data, err := ioutil.ReadFile(fs.proc.Path("net/arp"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error reading arp %s: %s", fs.proc.Path("net/arp"), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseARPEntries(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseARPEntries(data []byte) ([]ARPEntry, error) {
|
||||||
|
lines := strings.Split(string(data), "\n")
|
||||||
|
entries := make([]ARPEntry, 0)
|
||||||
|
var err error
|
||||||
|
const (
|
||||||
|
expectedDataWidth = 6
|
||||||
|
expectedHeaderWidth = 9
|
||||||
|
)
|
||||||
|
for _, line := range lines {
|
||||||
|
columns := strings.Fields(line)
|
||||||
|
width := len(columns)
|
||||||
|
|
||||||
|
if width == expectedHeaderWidth || width == 0 {
|
||||||
|
continue
|
||||||
|
} else if width == expectedDataWidth {
|
||||||
|
entry, err := parseARPEntry(columns)
|
||||||
|
if err != nil {
|
||||||
|
return []ARPEntry{}, fmt.Errorf("failed to parse ARP entry: %s", err)
|
||||||
|
}
|
||||||
|
entries = append(entries, entry)
|
||||||
|
} else {
|
||||||
|
return []ARPEntry{}, fmt.Errorf("%d columns were detected, but %d were expected", width, expectedDataWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseARPEntry(columns []string) (ARPEntry, error) {
|
||||||
|
ip := net.ParseIP(columns[0])
|
||||||
|
mac := net.HardwareAddr(columns[3])
|
||||||
|
|
||||||
|
entry := ARPEntry{
|
||||||
|
IPAddr: ip,
|
||||||
|
HWAddr: mac,
|
||||||
|
Device: columns[5],
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry, nil
|
||||||
|
}
|
131
vendor/github.com/prometheus/procfs/crypto.go
generated
vendored
Normal file
131
vendor/github.com/prometheus/procfs/crypto.go
generated
vendored
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
// Copyright 2019 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 procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/prometheus/procfs/internal/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Crypto holds info parsed from /proc/crypto.
|
||||||
|
type Crypto struct {
|
||||||
|
Alignmask *uint64
|
||||||
|
Async bool
|
||||||
|
Blocksize *uint64
|
||||||
|
Chunksize *uint64
|
||||||
|
Ctxsize *uint64
|
||||||
|
Digestsize *uint64
|
||||||
|
Driver string
|
||||||
|
Geniv string
|
||||||
|
Internal string
|
||||||
|
Ivsize *uint64
|
||||||
|
Maxauthsize *uint64
|
||||||
|
MaxKeysize *uint64
|
||||||
|
MinKeysize *uint64
|
||||||
|
Module string
|
||||||
|
Name string
|
||||||
|
Priority *int64
|
||||||
|
Refcnt *int64
|
||||||
|
Seedsize *uint64
|
||||||
|
Selftest string
|
||||||
|
Type string
|
||||||
|
Walksize *uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crypto parses an crypto-file (/proc/crypto) and returns a slice of
|
||||||
|
// structs containing the relevant info. More information available here:
|
||||||
|
// https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html
|
||||||
|
func (fs FS) Crypto() ([]Crypto, error) {
|
||||||
|
data, err := ioutil.ReadFile(fs.proc.Path("crypto"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error parsing crypto %s: %s", fs.proc.Path("crypto"), err)
|
||||||
|
}
|
||||||
|
crypto, err := parseCrypto(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error parsing crypto %s: %s", fs.proc.Path("crypto"), err)
|
||||||
|
}
|
||||||
|
return crypto, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCrypto(cryptoData []byte) ([]Crypto, error) {
|
||||||
|
crypto := []Crypto{}
|
||||||
|
|
||||||
|
cryptoBlocks := bytes.Split(cryptoData, []byte("\n\n"))
|
||||||
|
|
||||||
|
for _, block := range cryptoBlocks {
|
||||||
|
var newCryptoElem Crypto
|
||||||
|
|
||||||
|
lines := strings.Split(string(block), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.TrimSpace(line) == "" || line[0] == ' ' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fields := strings.Split(line, ":")
|
||||||
|
key := strings.TrimSpace(fields[0])
|
||||||
|
value := strings.TrimSpace(fields[1])
|
||||||
|
vp := util.NewValueParser(value)
|
||||||
|
|
||||||
|
switch strings.TrimSpace(key) {
|
||||||
|
case "async":
|
||||||
|
b, err := strconv.ParseBool(value)
|
||||||
|
if err == nil {
|
||||||
|
newCryptoElem.Async = b
|
||||||
|
}
|
||||||
|
case "blocksize":
|
||||||
|
newCryptoElem.Blocksize = vp.PUInt64()
|
||||||
|
case "chunksize":
|
||||||
|
newCryptoElem.Chunksize = vp.PUInt64()
|
||||||
|
case "digestsize":
|
||||||
|
newCryptoElem.Digestsize = vp.PUInt64()
|
||||||
|
case "driver":
|
||||||
|
newCryptoElem.Driver = value
|
||||||
|
case "geniv":
|
||||||
|
newCryptoElem.Geniv = value
|
||||||
|
case "internal":
|
||||||
|
newCryptoElem.Internal = value
|
||||||
|
case "ivsize":
|
||||||
|
newCryptoElem.Ivsize = vp.PUInt64()
|
||||||
|
case "maxauthsize":
|
||||||
|
newCryptoElem.Maxauthsize = vp.PUInt64()
|
||||||
|
case "max keysize":
|
||||||
|
newCryptoElem.MaxKeysize = vp.PUInt64()
|
||||||
|
case "min keysize":
|
||||||
|
newCryptoElem.MinKeysize = vp.PUInt64()
|
||||||
|
case "module":
|
||||||
|
newCryptoElem.Module = value
|
||||||
|
case "name":
|
||||||
|
newCryptoElem.Name = value
|
||||||
|
case "priority":
|
||||||
|
newCryptoElem.Priority = vp.PInt64()
|
||||||
|
case "refcnt":
|
||||||
|
newCryptoElem.Refcnt = vp.PInt64()
|
||||||
|
case "seedsize":
|
||||||
|
newCryptoElem.Seedsize = vp.PUInt64()
|
||||||
|
case "selftest":
|
||||||
|
newCryptoElem.Selftest = value
|
||||||
|
case "type":
|
||||||
|
newCryptoElem.Type = value
|
||||||
|
case "walksize":
|
||||||
|
newCryptoElem.Walksize = vp.PUInt64()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crypto = append(crypto, newCryptoElem)
|
||||||
|
}
|
||||||
|
return crypto, nil
|
||||||
|
}
|
91
vendor/github.com/prometheus/procfs/net_softnet.go
generated
vendored
Normal file
91
vendor/github.com/prometheus/procfs/net_softnet.go
generated
vendored
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
// Copyright 2019 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 procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// For the proc file format details,
|
||||||
|
// see https://elixir.bootlin.com/linux/v4.17/source/net/core/net-procfs.c#L162
|
||||||
|
// and https://elixir.bootlin.com/linux/v4.17/source/include/linux/netdevice.h#L2810.
|
||||||
|
|
||||||
|
// SoftnetEntry contains a single row of data from /proc/net/softnet_stat
|
||||||
|
type SoftnetEntry struct {
|
||||||
|
// Number of processed packets
|
||||||
|
Processed uint
|
||||||
|
// Number of dropped packets
|
||||||
|
Dropped uint
|
||||||
|
// Number of times processing packets ran out of quota
|
||||||
|
TimeSqueezed uint
|
||||||
|
}
|
||||||
|
|
||||||
|
// GatherSoftnetStats reads /proc/net/softnet_stat, parse the relevant columns,
|
||||||
|
// and then return a slice of SoftnetEntry's.
|
||||||
|
func (fs FS) GatherSoftnetStats() ([]SoftnetEntry, error) {
|
||||||
|
data, err := ioutil.ReadFile(fs.proc.Path("net/softnet_stat"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error reading softnet %s: %s", fs.proc.Path("net/softnet_stat"), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseSoftnetEntries(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSoftnetEntries(data []byte) ([]SoftnetEntry, error) {
|
||||||
|
lines := strings.Split(string(data), "\n")
|
||||||
|
entries := make([]SoftnetEntry, 0)
|
||||||
|
var err error
|
||||||
|
const (
|
||||||
|
expectedColumns = 11
|
||||||
|
)
|
||||||
|
for _, line := range lines {
|
||||||
|
columns := strings.Fields(line)
|
||||||
|
width := len(columns)
|
||||||
|
if width == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if width != expectedColumns {
|
||||||
|
return []SoftnetEntry{}, fmt.Errorf("%d columns were detected, but %d were expected", width, expectedColumns)
|
||||||
|
}
|
||||||
|
var entry SoftnetEntry
|
||||||
|
if entry, err = parseSoftnetEntry(columns); err != nil {
|
||||||
|
return []SoftnetEntry{}, err
|
||||||
|
}
|
||||||
|
entries = append(entries, entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSoftnetEntry(columns []string) (SoftnetEntry, error) {
|
||||||
|
var err error
|
||||||
|
var processed, dropped, timeSqueezed uint64
|
||||||
|
if processed, err = strconv.ParseUint(columns[0], 16, 32); err != nil {
|
||||||
|
return SoftnetEntry{}, fmt.Errorf("Unable to parse column 0: %s", err)
|
||||||
|
}
|
||||||
|
if dropped, err = strconv.ParseUint(columns[1], 16, 32); err != nil {
|
||||||
|
return SoftnetEntry{}, fmt.Errorf("Unable to parse column 1: %s", err)
|
||||||
|
}
|
||||||
|
if timeSqueezed, err = strconv.ParseUint(columns[2], 16, 32); err != nil {
|
||||||
|
return SoftnetEntry{}, fmt.Errorf("Unable to parse column 2: %s", err)
|
||||||
|
}
|
||||||
|
return SoftnetEntry{
|
||||||
|
Processed: uint(processed),
|
||||||
|
Dropped: uint(dropped),
|
||||||
|
TimeSqueezed: uint(timeSqueezed),
|
||||||
|
}, nil
|
||||||
|
}
|
90
vendor/github.com/prometheus/procfs/sysfs/class_cooling_device.go
generated
vendored
Normal file
90
vendor/github.com/prometheus/procfs/sysfs/class_cooling_device.go
generated
vendored
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
// Copyright 2019 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.
|
||||||
|
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package sysfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/prometheus/procfs/internal/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ClassCoolingDeviceStats contains info from files in /sys/class/thermal/cooling_device[0-9]*
|
||||||
|
// for a single device.
|
||||||
|
// https://www.kernel.org/doc/Documentation/thermal/sysfs-api.txt
|
||||||
|
type ClassCoolingDeviceStats struct {
|
||||||
|
Name string // The name of the cooling device.
|
||||||
|
Type string // Type of the cooling device(processor/fan/...)
|
||||||
|
MaxState int64 // Maximum cooling state of the cooling device
|
||||||
|
CurState int64 // Current cooling state of the cooling device
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs FS) ClassCoolingDeviceStats() ([]ClassCoolingDeviceStats, error) {
|
||||||
|
cds, err := filepath.Glob(fs.sys.Path("class/thermal/cooling_device[0-9]*"))
|
||||||
|
if err != nil {
|
||||||
|
return []ClassCoolingDeviceStats{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var coolingDeviceStats = ClassCoolingDeviceStats{}
|
||||||
|
stats := make([]ClassCoolingDeviceStats, len(cds))
|
||||||
|
for i, cd := range cds {
|
||||||
|
cdName := strings.TrimPrefix(filepath.Base(cd), "cooling_device")
|
||||||
|
|
||||||
|
coolingDeviceStats, err = parseCoolingDeviceStats(cd)
|
||||||
|
if err != nil {
|
||||||
|
return []ClassCoolingDeviceStats{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
coolingDeviceStats.Name = cdName
|
||||||
|
stats[i] = coolingDeviceStats
|
||||||
|
}
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCoolingDeviceStats(cd string) (ClassCoolingDeviceStats, error) {
|
||||||
|
cdType, err := util.SysReadFile(filepath.Join(cd, "type"))
|
||||||
|
if err != nil {
|
||||||
|
return ClassCoolingDeviceStats{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cdMaxStateString, err := util.SysReadFile(filepath.Join(cd, "max_state"))
|
||||||
|
if err != nil {
|
||||||
|
return ClassCoolingDeviceStats{}, err
|
||||||
|
}
|
||||||
|
cdMaxStateInt, err := strconv.ParseInt(cdMaxStateString, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ClassCoolingDeviceStats{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// cur_state can be -1, eg intel powerclamp
|
||||||
|
// https://www.kernel.org/doc/Documentation/thermal/intel_powerclamp.txt
|
||||||
|
cdCurStateString, err := util.SysReadFile(filepath.Join(cd, "cur_state"))
|
||||||
|
if err != nil {
|
||||||
|
return ClassCoolingDeviceStats{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cdCurStateInt, err := strconv.ParseInt(cdCurStateString, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return ClassCoolingDeviceStats{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ClassCoolingDeviceStats{
|
||||||
|
Type: cdType,
|
||||||
|
MaxState: cdMaxStateInt,
|
||||||
|
CurState: cdCurStateInt,
|
||||||
|
}, nil
|
||||||
|
}
|
84
vendor/github.com/prometheus/procfs/sysfs/vulnerability.go
generated
vendored
Normal file
84
vendor/github.com/prometheus/procfs/sysfs/vulnerability.go
generated
vendored
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// Copyright 2019 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 sysfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
notAffected = "Not Affected"
|
||||||
|
vulnerable = "Vulnerable"
|
||||||
|
mitigation = "Mitigation"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CPUVulnerabilities retrieves a map of vulnerability names to their mitigations.
|
||||||
|
func (fs FS) CPUVulnerabilities() ([]Vulnerability, error) {
|
||||||
|
matches, err := filepath.Glob(fs.sys.Path("devices/system/cpu/vulnerabilities/*"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
vulnerabilities := make([]Vulnerability, 0, len(matches))
|
||||||
|
for _, match := range matches {
|
||||||
|
name := filepath.Base(match)
|
||||||
|
|
||||||
|
value, err := ioutil.ReadFile(match)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := parseVulnerability(name, string(value))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
vulnerabilities = append(vulnerabilities, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return vulnerabilities, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vulnerability represents a single vulnerability extracted from /sys/devices/system/cpu/vulnerabilities/
|
||||||
|
type Vulnerability struct {
|
||||||
|
CodeName string
|
||||||
|
State string
|
||||||
|
Mitigation string
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseVulnerability(name, value string) (Vulnerability, error) {
|
||||||
|
v := Vulnerability{CodeName: name}
|
||||||
|
value = strings.TrimSpace(value)
|
||||||
|
if value == notAffected {
|
||||||
|
v.State = notAffected
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(value, vulnerable) {
|
||||||
|
v.State = vulnerable
|
||||||
|
v.Mitigation = strings.TrimPrefix(strings.TrimPrefix(value, vulnerable), ": ")
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(value, mitigation) {
|
||||||
|
v.State = mitigation
|
||||||
|
v.Mitigation = strings.TrimPrefix(strings.TrimPrefix(value, mitigation), ": ")
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return v, fmt.Errorf("unknown vulnerability state for %s: %s", name, value)
|
||||||
|
}
|
Loading…
Reference in a new issue