mirror of
https://github.com/prometheus/node_exporter
synced 2025-03-08 19:37:44 +00:00
Remove all hardcoded references to `/proc`. For all collectors that do not use `github.com/prometheus/procfs` yet, provide a wrapper to generate the full paths. Reformulate help strings, errors and comments to remove absolute references to `/proc`. This is a breaking change: the `-collector.ipvs.procfs` flag is removed in favor of the general flag. Since it only affected that collector it was only useful for development, so this should not cause many issues.
116 lines
2.9 KiB
Go
116 lines
2.9 KiB
Go
// +build !nonetdev
|
|
|
|
package collector
|
|
|
|
import (
|
|
"bufio"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/prometheus/log"
|
|
)
|
|
|
|
var (
|
|
procNetDevFieldSep = regexp.MustCompile("[ :] *")
|
|
netdevIgnoredDevices = flag.String(
|
|
"collector.netdev.ignored-devices", "^$",
|
|
"Regexp of net devices to ignore for netdev collector.")
|
|
)
|
|
|
|
type netDevCollector struct {
|
|
subsystem string
|
|
ignoredDevicesPattern *regexp.Regexp
|
|
metricDescs map[string]*prometheus.Desc
|
|
}
|
|
|
|
func init() {
|
|
Factories["netdev"] = NewNetDevCollector
|
|
}
|
|
|
|
// Takes a prometheus registry and returns a new Collector exposing
|
|
// network device stats.
|
|
func NewNetDevCollector() (Collector, error) {
|
|
pattern := regexp.MustCompile(*netdevIgnoredDevices)
|
|
return &netDevCollector{
|
|
subsystem: "network",
|
|
ignoredDevicesPattern: pattern,
|
|
metricDescs: map[string]*prometheus.Desc{},
|
|
}, nil
|
|
}
|
|
|
|
func (c *netDevCollector) Update(ch chan<- prometheus.Metric) (err error) {
|
|
netDev, err := getNetDevStats(c.ignoredDevicesPattern)
|
|
if err != nil {
|
|
return fmt.Errorf("couldn't get netstats: %s", err)
|
|
}
|
|
for dev, devStats := range netDev {
|
|
for key, value := range devStats {
|
|
desc, ok := c.metricDescs[key]
|
|
if !ok {
|
|
desc = prometheus.NewDesc(
|
|
prometheus.BuildFQName(Namespace, c.subsystem, key),
|
|
fmt.Sprintf("Network device statistic %s.", key),
|
|
[]string{"device"},
|
|
nil,
|
|
)
|
|
c.metricDescs[key] = desc
|
|
}
|
|
v, err := strconv.ParseFloat(value, 64)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid value %s in netstats: %s", value, err)
|
|
}
|
|
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, v, dev)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func getNetDevStats(ignore *regexp.Regexp) (map[string]map[string]string, error) {
|
|
file, err := os.Open(procFilePath("net/dev"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer file.Close()
|
|
|
|
return parseNetDevStats(file, ignore)
|
|
}
|
|
|
|
func parseNetDevStats(r io.Reader, ignore *regexp.Regexp) (map[string]map[string]string, error) {
|
|
scanner := bufio.NewScanner(r)
|
|
scanner.Scan() // skip first header
|
|
scanner.Scan()
|
|
parts := strings.Split(string(scanner.Text()), "|")
|
|
if len(parts) != 3 { // interface + receive + transmit
|
|
return nil, fmt.Errorf("invalid header line in net/dev: %s",
|
|
scanner.Text())
|
|
}
|
|
|
|
header := strings.Fields(parts[1])
|
|
netDev := map[string]map[string]string{}
|
|
for scanner.Scan() {
|
|
line := strings.TrimLeft(string(scanner.Text()), " ")
|
|
parts := procNetDevFieldSep.Split(line, -1)
|
|
if len(parts) != 2*len(header)+1 {
|
|
return nil, fmt.Errorf("invalid line in net/dev: %s", scanner.Text())
|
|
}
|
|
|
|
dev := parts[0][:len(parts[0])]
|
|
if ignore.MatchString(dev) {
|
|
log.Debugf("Ignoring device: %s", dev)
|
|
continue
|
|
}
|
|
netDev[dev] = map[string]string{}
|
|
for i, v := range header {
|
|
netDev[dev]["receive_"+v] = parts[i+1]
|
|
netDev[dev]["transmit_"+v] = parts[i+1+len(header)]
|
|
}
|
|
}
|
|
return netDev, nil
|
|
}
|