Migrate arp_linux.go to procfs
Signed-off-by: James Bach <qweet.ing@gmail.com> Signed-off-by: James Bach <james.bach@wise.com> Signed-off-by: jalev <qweet.ing@gmail.com>pull/2553/head
parent
da08a2959f
commit
5538773089
|
@ -17,14 +17,10 @@
|
||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/go-kit/log"
|
"github.com/go-kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"github.com/prometheus/procfs"
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -34,6 +30,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type arpCollector struct {
|
type arpCollector struct {
|
||||||
|
fs procfs.FS
|
||||||
deviceFilter deviceFilter
|
deviceFilter deviceFilter
|
||||||
entries *prometheus.Desc
|
entries *prometheus.Desc
|
||||||
logger log.Logger
|
logger log.Logger
|
||||||
|
@ -45,7 +42,13 @@ func init() {
|
||||||
|
|
||||||
// NewARPCollector returns a new Collector exposing ARP stats.
|
// NewARPCollector returns a new Collector exposing ARP stats.
|
||||||
func NewARPCollector(logger log.Logger) (Collector, error) {
|
func NewARPCollector(logger log.Logger) (Collector, error) {
|
||||||
|
fs, err := procfs.NewFS(*procPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to open procfs: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return &arpCollector{
|
return &arpCollector{
|
||||||
|
fs: fs,
|
||||||
deviceFilter: newDeviceFilter(*arpDeviceExclude, *arpDeviceInclude),
|
deviceFilter: newDeviceFilter(*arpDeviceExclude, *arpDeviceInclude),
|
||||||
entries: prometheus.NewDesc(
|
entries: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, "arp", "entries"),
|
prometheus.BuildFQName(namespace, "arp", "entries"),
|
||||||
|
@ -56,61 +59,30 @@ func NewARPCollector(logger log.Logger) (Collector, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getARPEntries() (map[string]uint32, error) {
|
func getTotalArpEntries(deviceEntries []procfs.ARPEntry) map[string]uint32 {
|
||||||
file, err := os.Open(procFilePath("net/arp"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
entries, err := parseARPEntries(file)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return entries, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This should get extracted to the github.com/prometheus/procfs package
|
|
||||||
// to support more complete parsing of /proc/net/arp. Instead of adding
|
|
||||||
// more fields to this function's return values it should get moved and
|
|
||||||
// changed to support each field.
|
|
||||||
func parseARPEntries(data io.Reader) (map[string]uint32, error) {
|
|
||||||
scanner := bufio.NewScanner(data)
|
|
||||||
entries := make(map[string]uint32)
|
entries := make(map[string]uint32)
|
||||||
|
|
||||||
for scanner.Scan() {
|
for _, device := range deviceEntries {
|
||||||
columns := strings.Fields(scanner.Text())
|
entries[device.Device] += 1
|
||||||
|
|
||||||
if len(columns) < 6 {
|
|
||||||
return nil, fmt.Errorf("unexpected ARP table format")
|
|
||||||
}
|
|
||||||
|
|
||||||
if columns[0] != "IP" {
|
|
||||||
deviceIndex := len(columns) - 1
|
|
||||||
entries[columns[deviceIndex]]++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
return entries
|
||||||
return nil, fmt.Errorf("failed to parse ARP info: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return entries, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *arpCollector) Update(ch chan<- prometheus.Metric) error {
|
func (c *arpCollector) Update(ch chan<- prometheus.Metric) error {
|
||||||
entries, err := getARPEntries()
|
entries, err := c.fs.GatherARPEntries()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not get ARP entries: %w", err)
|
return fmt.Errorf("could not get ARP entries: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for device, entryCount := range entries {
|
enumeratedEntry := getTotalArpEntries(entries)
|
||||||
|
|
||||||
|
for device, entry := range enumeratedEntry {
|
||||||
if c.deviceFilter.ignored(device) {
|
if c.deviceFilter.ignored(device) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ch <- prometheus.MustNewConstMetric(
|
ch <- prometheus.MustNewConstMetric(
|
||||||
c.entries, prometheus.GaugeValue, float64(entryCount), device)
|
c.entries, prometheus.GaugeValue, float64(entry), device)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Reference in New Issue