Skip to content

Commit

Permalink
Add --collector.netdev.device-whitelist flag (prometheus#1279)
Browse files Browse the repository at this point in the history
* Add --collector.netdev.device-whitelist flag

Sometimes it is desired to monitor only one netdev. The golang regexp
does not support a negated regex, so the ignored-devices flag is too
cumbersome for this task.
This change introduces a new flag: accept-devices, which is mutually
exclusive to ignored-devices. This flag allows specifying ONLY the
netdev you'd like.

Signed-off-by: Noam Meltzer <[email protected]>
  • Loading branch information
tsnoam authored and SuperQ committed May 31, 2019
1 parent fc02b5d commit 501ccf9
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 16 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

### **Breaking changes**

* The netdev collector CLI argument `--collector.netdev.ignored-devices` was renamed to `--collector.netdev.device-blacklist` in order to conform with the systemd collector. #1279


### Changes

* [CHANGE]
* [CHANGE] Add `--collector.netdev.device-whitelist`. #1279
* [FEATURE]
* [ENHANCEMENT]
* [BUGFIX] Fix incorrect sysctl call in BSD meminfo collector, resulting in broken swap metrics on FreeBSD #1345
Expand Down
8 changes: 6 additions & 2 deletions collector/netdev_bsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import (
*/
import "C"

func getNetDevStats(ignore *regexp.Regexp) (map[string]map[string]string, error) {
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp) (map[string]map[string]string, error) {
netDev := map[string]map[string]string{}

var ifap, ifa *C.struct_ifaddrs
Expand All @@ -46,7 +46,11 @@ func getNetDevStats(ignore *regexp.Regexp) (map[string]map[string]string, error)
for ifa = ifap; ifa != nil; ifa = ifa.ifa_next {
if ifa.ifa_addr.sa_family == C.AF_LINK {
dev := C.GoString(ifa.ifa_name)
if ignore.MatchString(dev) {
if ignore != nil && ignore.MatchString(dev) {
log.Debugf("Ignoring device: %s", dev)
continue
}
if accept != nil && !accept.MatchString(dev) {
log.Debugf("Ignoring device: %s", dev)
continue
}
Expand Down
25 changes: 21 additions & 4 deletions collector/netdev_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package collector

import (
"errors"
"fmt"
"regexp"
"strconv"
Expand All @@ -26,12 +27,14 @@ import (
)

var (
netdevIgnoredDevices = kingpin.Flag("collector.netdev.ignored-devices", "Regexp of net devices to ignore for netdev collector.").Default("^$").String()
netdevIgnoredDevices = kingpin.Flag("collector.netdev.device-blacklist", "Regexp of net devices to blacklist (mutually exclusive to device-whitelist).").String()
netdevAcceptDevices = kingpin.Flag("collector.netdev.device-whitelist", "Regexp of net devices to whitelist (mutually exclusive to device-blacklist).").String()
)

type netDevCollector struct {
subsystem string
ignoredDevicesPattern *regexp.Regexp
acceptDevicesPattern *regexp.Regexp
metricDescs map[string]*prometheus.Desc
}

Expand All @@ -41,16 +44,30 @@ func init() {

// NewNetDevCollector returns a new Collector exposing network device stats.
func NewNetDevCollector() (Collector, error) {
pattern := regexp.MustCompile(*netdevIgnoredDevices)
if *netdevIgnoredDevices != "" && *netdevAcceptDevices != "" {
return nil, errors.New("device-blacklist & accept-devices are mutually exclusive")
}

var ignorePattern *regexp.Regexp = nil
if *netdevIgnoredDevices != "" {
ignorePattern = regexp.MustCompile(*netdevIgnoredDevices)
}

var acceptPattern *regexp.Regexp = nil
if *netdevAcceptDevices != "" {
acceptPattern = regexp.MustCompile(*netdevAcceptDevices)
}

return &netDevCollector{
subsystem: "network",
ignoredDevicesPattern: pattern,
ignoredDevicesPattern: ignorePattern,
acceptDevicesPattern: acceptPattern,
metricDescs: map[string]*prometheus.Desc{},
}, nil
}

func (c *netDevCollector) Update(ch chan<- prometheus.Metric) error {
netDev, err := getNetDevStats(c.ignoredDevicesPattern)
netDev, err := getNetDevStats(c.ignoredDevicesPattern, c.acceptDevicesPattern)
if err != nil {
return fmt.Errorf("couldn't get netstats: %s", err)
}
Expand Down
6 changes: 5 additions & 1 deletion collector/netdev_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
"golang.org/x/sys/unix"
)

func getNetDevStats(ignore *regexp.Regexp) (map[string]map[string]string, error) {
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp) (map[string]map[string]string, error) {
netDev := map[string]map[string]string{}

ifs, err := net.Interfaces()
Expand All @@ -46,6 +46,10 @@ func getNetDevStats(ignore *regexp.Regexp) (map[string]map[string]string, error)
log.Debugf("Ignoring device: %s", iface.Name)
continue
}
if accept != nil && !accept.MatchString(iface.Name) {
log.Debugf("Ignoring device: %s", iface.Name)
continue
}

devStats := map[string]string{}
devStats["receive_packets"] = strconv.FormatUint(ifaceData.Data.Ipackets, 10)
Expand Down
12 changes: 8 additions & 4 deletions collector/netdev_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,17 @@ var (
procNetDevFieldSep = regexp.MustCompile(` +`)
)

func getNetDevStats(ignore *regexp.Regexp) (map[string]map[string]string, error) {
func getNetDevStats(ignore *regexp.Regexp, accept *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)
return parseNetDevStats(file, ignore, accept)
}

func parseNetDevStats(r io.Reader, ignore *regexp.Regexp) (map[string]map[string]string, error) {
func parseNetDevStats(r io.Reader, ignore *regexp.Regexp, accept *regexp.Regexp) (map[string]map[string]string, error) {
scanner := bufio.NewScanner(r)
scanner.Scan() // skip first header
scanner.Scan()
Expand All @@ -64,7 +64,11 @@ func parseNetDevStats(r io.Reader, ignore *regexp.Regexp) (map[string]map[string
}

dev := parts[1]
if ignore.MatchString(dev) {
if ignore != nil && ignore.MatchString(dev) {
log.Debugf("Ignoring device: %s", dev)
continue
}
if accept != nil && !accept.MatchString(dev) {
log.Debugf("Ignoring device: %s", dev)
continue
}
Expand Down
24 changes: 22 additions & 2 deletions collector/netdev_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ import (
"testing"
)

func TestNetDevStats(t *testing.T) {
func TestNetDevStatsIgnore(t *testing.T) {
file, err := os.Open("fixtures/proc/net/dev")
if err != nil {
t.Fatal(err)
}
defer file.Close()

netStats, err := parseNetDevStats(file, regexp.MustCompile("^veth"))
netStats, err := parseNetDevStats(file, regexp.MustCompile("^veth"), nil)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -59,3 +59,23 @@ func TestNetDevStats(t *testing.T) {
t.Error("want fixture interface 💩0 to exist, but it does not")
}
}

func TestNetDevStatsAccept(t *testing.T) {
file, err := os.Open("fixtures/proc/net/dev")
if err != nil {
t.Fatal(err)
}
defer file.Close()

netStats, err := parseNetDevStats(file, nil, regexp.MustCompile("^💩0$"))
if err != nil {
t.Fatal(err)
}

if want, got := 1, len(netStats); want != got {
t.Errorf("want count of devices to be %d, got %d", want, got)
}
if want, got := "72", netStats["💩0"]["receive_multicast"]; want != got {
t.Error("want fixture interface 💩0 to exist, but it does not")
}
}
8 changes: 6 additions & 2 deletions collector/netdev_openbsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
*/
import "C"

func getNetDevStats(ignore *regexp.Regexp) (map[string]map[string]string, error) {
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp) (map[string]map[string]string, error) {
netDev := map[string]map[string]string{}

var ifap, ifa *C.struct_ifaddrs
Expand All @@ -43,7 +43,11 @@ func getNetDevStats(ignore *regexp.Regexp) (map[string]map[string]string, error)
for ifa = ifap; ifa != nil; ifa = ifa.ifa_next {
if ifa.ifa_addr.sa_family == C.AF_LINK {
dev := C.GoString(ifa.ifa_name)
if ignore.MatchString(dev) {
if ignore != nil && ignore.MatchString(dev) {
log.Debugf("Ignoring device: %s", dev)
continue
}
if accept != nil && !accept.MatchString(dev) {
log.Debugf("Ignoring device: %s", dev)
continue
}
Expand Down

0 comments on commit 501ccf9

Please sign in to comment.