Skip to content

Commit

Permalink
Merge branch 'master' of github.com:prometheus/node_exporter into add…
Browse files Browse the repository at this point in the history
…-arp-states

Signed-off-by: Emin Umut Gercek <[email protected]>
  • Loading branch information
eugercek committed Jan 13, 2025
2 parents 2246604 + acdd9b8 commit d679000
Show file tree
Hide file tree
Showing 30 changed files with 1,168 additions and 1,061 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Install Go
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: 1.23.x
- name: Install snmp_exporter/generator dependencies
Expand All @@ -36,4 +36,4 @@ jobs:
uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1
with:
args: --verbose
version: v1.61.0
version: v1.62.0
10 changes: 1 addition & 9 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
linters:
enable:
- depguard
- goimports
- misspell
- revive
disable:
# Disable soon to deprecated[1] linters that lead to false
# positives when build tags disable certain files[2]
# 1: https://github.com/golangci/golangci-lint/issues/1841
# 2: https://github.com/prometheus/node_exporter/issues/1545
- deadcode
- unused
- structcheck
- varcheck

issues:
exclude-rules:
Expand Down
2 changes: 1 addition & 1 deletion Makefile.common
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_
SKIP_GOLANGCI_LINT :=
GOLANGCI_LINT :=
GOLANGCI_LINT_OPTS ?=
GOLANGCI_LINT_VERSION ?= v1.61.0
GOLANGCI_LINT_VERSION ?= v1.62.0
# golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64.
# windows isn't included here because of the path separator being different.
ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin))
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ cpu | flags | --collector.cpu.info.flags-include | N/A
diskstats | device | --collector.diskstats.device-include | --collector.diskstats.device-exclude
ethtool | device | --collector.ethtool.device-include | --collector.ethtool.device-exclude
ethtool | metrics | --collector.ethtool.metrics-include | N/A
filesystem | fs-types | N/A | --collector.filesystem.fs-types-exclude
filesystem | mount-points | N/A | --collector.filesystem.mount-points-exclude
filesystem | fs-types | --collector.filesystem.fs-types-include | --collector.filesystem.fs-types-exclude
filesystem | mount-points | --collector.filesystem.mount-points-include | --collector.filesystem.mount-points-exclude
hwmon | chip | --collector.hwmon.chip-include | --collector.hwmon.chip-exclude
hwmon | sensor | --collector.hwmon.sensor-include | --collector.hwmon.sensor-exclude
interrupts | name | --collector.interrupts.name-include | --collector.interrupts.name-exclude
Expand Down
50 changes: 18 additions & 32 deletions collector/arp_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@
package collector

import (
"errors"
"fmt"
"log/slog"
"net"

"github.com/alecthomas/kingpin/v2"
"github.com/jsimonetti/rtnetlink/v2"
"github.com/jsimonetti/rtnetlink/v2/rtnl"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/procfs"
"golang.org/x/sys/unix"
Expand Down Expand Up @@ -97,53 +95,41 @@ func getTotalArpEntries(deviceEntries []procfs.ARPEntry) map[string]uint32 {
}

func getArpEntriesRTNL() (map[string]uint32, map[string]map[string]int, error) {
conn, err := rtnetlink.Dial(nil)
conn, err := rtnl.Dial(nil)
if err != nil {
return nil, nil, err
}
defer conn.Close()

neighbors, err := conn.Neigh.List()
// Neighbors will also contain IPv6 neighbors, but since this is purely an ARP collector,
// restrict to AF_INET.
neighbors, err := conn.Neighbours(nil, unix.AF_INET)
if err != nil {
return nil, nil, err
}

ifIndexEntries := make(map[uint32]uint32)
ifIndexStates := make(map[uint32]map[string]int)
// Map of interface name to ARP neighbor count.
entries := make(map[string]uint32)
// Map of map[InterfaceName]map[StateName]int
states := make(map[string]map[string]int)

for _, n := range neighbors {
// Neighbors will also contain IPv6 neighbors, but since this is purely an ARP collector,
// restrict to AF_INET. Also skip entries which have state NUD_NOARP to conform to output
// of /proc/net/arp.
if n.Family == unix.AF_INET && n.State&unix.NUD_NOARP == 0 {
ifIndexEntries[n.Index]++

_, ok := ifIndexStates[n.Index]
if !ok {
ifIndexStates[n.Index] = make(map[string]int)
}
ifIndexStates[n.Index][neighborStatesMap[n.State]]++
// Skip entries which have state NUD_NOARP to conform to output of /proc/net/arp.
if n.State&unix.NUD_NOARP != unix.NUD_NOARP {
continue
}
}

enumEntries := make(map[string]uint32)
enumStates := make(map[string]map[string]int)
entries[n.Interface.Name]++

// Convert interface indexes to names.
for ifIndex, entryCount := range ifIndexEntries {
iface, err := net.InterfaceByIndex(int(ifIndex))
if err != nil {
if errors.Unwrap(err).Error() == "no such network interface" {
continue
}
return nil, nil, err
_, ok := states[n.Interface.Name]
if !ok {
states[n.Interface.Name] = make(map[string]int)
}

enumEntries[iface.Name] = entryCount
enumStates[iface.Name] = ifIndexStates[ifIndex]
states[n.Interface.Name][neighborStatesMap[n.State]]++
}

return enumEntries, enumStates, nil
return entries, states, nil
}

func (c *arpCollector) Update(ch chan<- prometheus.Metric) error {
Expand Down
61 changes: 51 additions & 10 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"
"log/slog"
"os"
Expand All @@ -26,15 +27,17 @@ import (
"strconv"
"sync"

"golang.org/x/exp/maps"

"github.com/alecthomas/kingpin/v2"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/procfs"
"github.com/prometheus/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 +48,7 @@ type cpuCollector struct {
cpuPackageThrottle *prometheus.Desc
cpuIsolated *prometheus.Desc
logger *slog.Logger
cpuOnline *prometheus.Desc
cpuStats map[int64]procfs.CPUStat
cpuStatsMutex sync.Mutex
isolatedCpus []uint16
Expand All @@ -70,17 +74,17 @@ func init() {

// NewCPUCollector returns a new Collector exposing kernel/system statistics.
func NewCPUCollector(logger *slog.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 @@ -89,8 +93,9 @@ func NewCPUCollector(logger *slog.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 @@ -131,6 +136,11 @@ func NewCPUCollector(logger *slog.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 @@ -177,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 @@ -333,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
5 changes: 3 additions & 2 deletions collector/cpufreq_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ package collector

import (
"fmt"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/procfs/sysfs"
"log/slog"
"strings"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/procfs/sysfs"
)

type cpuFreqCollector struct {
Expand Down
4 changes: 2 additions & 2 deletions collector/filesystem_aix.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) {
return nil, err
}
for _, stat := range fsStat {
if c.excludedMountPointsPattern.MatchString(stat.MountPoint) {
if c.mountPointFilter.ignored(stat.MountPoint) {
c.logger.Debug("Ignoring mount point", "mountpoint", stat.MountPoint)
continue
}
fstype := stat.TypeString()
if c.excludedFSTypesPattern.MatchString(fstype) {
if c.fsTypeFilter.ignored(fstype) {
c.logger.Debug("Ignoring fs type", "type", fstype)
continue
}
Expand Down
4 changes: 2 additions & 2 deletions collector/filesystem_bsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) {
stats = []filesystemStats{}
for i := 0; i < int(count); i++ {
mountpoint := C.GoString(&mnt[i].f_mntonname[0])
if c.excludedMountPointsPattern.MatchString(mountpoint) {
if c.mountPointFilter.ignored(mountpoint) {
c.logger.Debug("Ignoring mount point", "mountpoint", mountpoint)
continue
}

device := C.GoString(&mnt[i].f_mntfromname[0])
fstype := C.GoString(&mnt[i].f_fstypename[0])
if c.excludedFSTypesPattern.MatchString(fstype) {
if c.fsTypeFilter.ignored(fstype) {
c.logger.Debug("Ignoring fs type", "type", fstype)
continue
}
Expand Down
Loading

0 comments on commit d679000

Please sign in to comment.