mirror of
https://github.com/prometheus/node_exporter.git
synced 2024-12-26 22:19:44 -08:00
Netdev tweaks (#1558)
* Check interface name before loading interface data * Reduce indentation * Optimize nested netdev map This change avoids conversion to strings and back. Signed-off-by: Julian Kornberger <jk+github@digineo.de>
This commit is contained in:
parent
0478ddef69
commit
66fb6762bf
|
@ -19,7 +19,6 @@ package collector
|
|||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/log/level"
|
||||
|
@ -35,8 +34,8 @@ import (
|
|||
*/
|
||||
import "C"
|
||||
|
||||
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (map[string]map[string]string, error) {
|
||||
netDev := map[string]map[string]string{}
|
||||
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (netDevStats, error) {
|
||||
netDev := netDevStats{}
|
||||
|
||||
var ifap, ifa *C.struct_ifaddrs
|
||||
if C.getifaddrs(&ifap) == -1 {
|
||||
|
@ -45,37 +44,35 @@ func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Log
|
|||
defer C.freeifaddrs(ifap)
|
||||
|
||||
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 != nil && ignore.MatchString(dev) {
|
||||
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
|
||||
continue
|
||||
}
|
||||
if accept != nil && !accept.MatchString(dev) {
|
||||
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
|
||||
continue
|
||||
}
|
||||
if ifa.ifa_addr.sa_family != C.AF_LINK {
|
||||
continue
|
||||
}
|
||||
|
||||
devStats := map[string]string{}
|
||||
data := (*C.struct_if_data)(ifa.ifa_data)
|
||||
dev := C.GoString(ifa.ifa_name)
|
||||
if ignore != nil && ignore.MatchString(dev) {
|
||||
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
|
||||
continue
|
||||
}
|
||||
if accept != nil && !accept.MatchString(dev) {
|
||||
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
|
||||
continue
|
||||
}
|
||||
|
||||
devStats["receive_packets"] = convertFreeBSDCPUTime(uint64(data.ifi_ipackets))
|
||||
devStats["transmit_packets"] = convertFreeBSDCPUTime(uint64(data.ifi_opackets))
|
||||
devStats["receive_errs"] = convertFreeBSDCPUTime(uint64(data.ifi_ierrors))
|
||||
devStats["transmit_errs"] = convertFreeBSDCPUTime(uint64(data.ifi_oerrors))
|
||||
devStats["receive_bytes"] = convertFreeBSDCPUTime(uint64(data.ifi_ibytes))
|
||||
devStats["transmit_bytes"] = convertFreeBSDCPUTime(uint64(data.ifi_obytes))
|
||||
devStats["receive_multicast"] = convertFreeBSDCPUTime(uint64(data.ifi_imcasts))
|
||||
devStats["transmit_multicast"] = convertFreeBSDCPUTime(uint64(data.ifi_omcasts))
|
||||
devStats["receive_drop"] = convertFreeBSDCPUTime(uint64(data.ifi_iqdrops))
|
||||
devStats["transmit_drop"] = convertFreeBSDCPUTime(uint64(data.ifi_oqdrops))
|
||||
netDev[dev] = devStats
|
||||
data := (*C.struct_if_data)(ifa.ifa_data)
|
||||
|
||||
netDev[dev] = map[string]uint64{
|
||||
"receive_packets": uint64(data.ifi_ipackets),
|
||||
"transmit_packets": uint64(data.ifi_opackets),
|
||||
"receive_errs": uint64(data.ifi_ierrors),
|
||||
"transmit_errs": uint64(data.ifi_oerrors),
|
||||
"receive_bytes": uint64(data.ifi_ibytes),
|
||||
"transmit_bytes": uint64(data.ifi_obytes),
|
||||
"receive_multicast": uint64(data.ifi_imcasts),
|
||||
"transmit_multicast": uint64(data.ifi_omcasts),
|
||||
"receive_drop": uint64(data.ifi_iqdrops),
|
||||
"transmit_drop": uint64(data.ifi_oqdrops),
|
||||
}
|
||||
}
|
||||
|
||||
return netDev, nil
|
||||
}
|
||||
|
||||
func convertFreeBSDCPUTime(counter uint64) string {
|
||||
return strconv.FormatUint(counter, 10)
|
||||
}
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
// Copyright 2016 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 !nonetdev
|
||||
// +build freebsd dragonfly
|
||||
|
||||
package collector
|
||||
|
||||
import "testing"
|
||||
|
||||
type uintToStringTest struct {
|
||||
in uint64
|
||||
out string
|
||||
}
|
||||
|
||||
var uinttostringtests = []uintToStringTest{
|
||||
// Copied base10 values from strconv's tests:
|
||||
{0, "0"},
|
||||
{1, "1"},
|
||||
{12345678, "12345678"},
|
||||
{1<<31 - 1, "2147483647"},
|
||||
{1 << 31, "2147483648"},
|
||||
{1<<31 + 1, "2147483649"},
|
||||
{1<<32 - 1, "4294967295"},
|
||||
{1 << 32, "4294967296"},
|
||||
{1<<32 + 1, "4294967297"},
|
||||
{1 << 50, "1125899906842624"},
|
||||
{1<<63 - 1, "9223372036854775807"},
|
||||
|
||||
// Some values that convert correctly on amd64, but not on i386.
|
||||
{0x1bf0c640a, "7500227594"},
|
||||
{0xbee5df75, "3202735989"},
|
||||
}
|
||||
|
||||
func TestUintToString(t *testing.T) {
|
||||
for _, test := range uinttostringtests {
|
||||
is := convertFreeBSDCPUTime(test.in)
|
||||
if is != test.out {
|
||||
t.Errorf("convertFreeBSDCPUTime(%v) = %v want %v",
|
||||
test.in, is, test.out)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,7 +20,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/log/level"
|
||||
|
@ -43,6 +42,8 @@ type netDevCollector struct {
|
|||
logger log.Logger
|
||||
}
|
||||
|
||||
type netDevStats map[string]map[string]uint64
|
||||
|
||||
func init() {
|
||||
registerCollector("netdev", defaultEnabled, NewNetDevCollector)
|
||||
}
|
||||
|
@ -109,11 +110,7 @@ func (c *netDevCollector) Update(ch chan<- prometheus.Metric) error {
|
|||
)
|
||||
c.metricDescs[key] = desc
|
||||
}
|
||||
v, err := strconv.ParseFloat(value, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid value %s in netstats: %w", value, err)
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(desc, prometheus.CounterValue, v, dev)
|
||||
ch <- prometheus.MustNewConstMetric(desc, prometheus.CounterValue, float64(value), dev)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -21,15 +21,14 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/log/level"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (map[string]map[string]string, error) {
|
||||
netDev := map[string]map[string]string{}
|
||||
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (netDevStats, error) {
|
||||
netDev := netDevStats{}
|
||||
|
||||
ifs, err := net.Interfaces()
|
||||
if err != nil {
|
||||
|
@ -37,12 +36,6 @@ func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Log
|
|||
}
|
||||
|
||||
for _, iface := range ifs {
|
||||
ifaceData, err := getIfaceData(iface.Index)
|
||||
if err != nil {
|
||||
level.Debug(logger).Log("msg", "failed to load data for interface", "device", iface.Name, "err", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if ignore != nil && ignore.MatchString(iface.Name) {
|
||||
level.Debug(logger).Log("msg", "Ignoring device", "device", iface.Name)
|
||||
continue
|
||||
|
@ -52,16 +45,22 @@ func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Log
|
|||
continue
|
||||
}
|
||||
|
||||
devStats := map[string]string{}
|
||||
devStats["receive_packets"] = strconv.FormatUint(ifaceData.Data.Ipackets, 10)
|
||||
devStats["transmit_packets"] = strconv.FormatUint(ifaceData.Data.Opackets, 10)
|
||||
devStats["receive_errs"] = strconv.FormatUint(ifaceData.Data.Ierrors, 10)
|
||||
devStats["transmit_errs"] = strconv.FormatUint(ifaceData.Data.Oerrors, 10)
|
||||
devStats["receive_bytes"] = strconv.FormatUint(ifaceData.Data.Ibytes, 10)
|
||||
devStats["transmit_bytes"] = strconv.FormatUint(ifaceData.Data.Obytes, 10)
|
||||
devStats["receive_multicast"] = strconv.FormatUint(ifaceData.Data.Imcasts, 10)
|
||||
devStats["transmit_multicast"] = strconv.FormatUint(ifaceData.Data.Omcasts, 10)
|
||||
netDev[iface.Name] = devStats
|
||||
ifaceData, err := getIfaceData(iface.Index)
|
||||
if err != nil {
|
||||
level.Debug(logger).Log("msg", "failed to load data for interface", "device", iface.Name, "err", err)
|
||||
continue
|
||||
}
|
||||
|
||||
netDev[iface.Name] = map[string]uint64{
|
||||
"receive_packets": ifaceData.Data.Ipackets,
|
||||
"transmit_packets": ifaceData.Data.Opackets,
|
||||
"receive_errs": ifaceData.Data.Ierrors,
|
||||
"transmit_errs": ifaceData.Data.Oerrors,
|
||||
"receive_bytes": ifaceData.Data.Ibytes,
|
||||
"transmit_bytes": ifaceData.Data.Obytes,
|
||||
"receive_multicast": ifaceData.Data.Imcasts,
|
||||
"transmit_multicast": ifaceData.Data.Omcasts,
|
||||
}
|
||||
}
|
||||
|
||||
return netDev, nil
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"io"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-kit/kit/log"
|
||||
|
@ -32,7 +33,7 @@ var (
|
|||
procNetDevFieldSep = regexp.MustCompile(` +`)
|
||||
)
|
||||
|
||||
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (map[string]map[string]string, error) {
|
||||
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (netDevStats, error) {
|
||||
file, err := os.Open(procFilePath("net/dev"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -42,7 +43,7 @@ func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Log
|
|||
return parseNetDevStats(file, ignore, accept, logger)
|
||||
}
|
||||
|
||||
func parseNetDevStats(r io.Reader, ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (map[string]map[string]string, error) {
|
||||
func parseNetDevStats(r io.Reader, ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (netDevStats, error) {
|
||||
scanner := bufio.NewScanner(r)
|
||||
scanner.Scan() // skip first header
|
||||
scanner.Scan()
|
||||
|
@ -56,7 +57,7 @@ func parseNetDevStats(r io.Reader, ignore *regexp.Regexp, accept *regexp.Regexp,
|
|||
transmitHeader := strings.Fields(parts[2])
|
||||
headerLength := len(receiveHeader) + len(transmitHeader)
|
||||
|
||||
netDev := map[string]map[string]string{}
|
||||
netDev := netDevStats{}
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimLeft(scanner.Text(), " ")
|
||||
parts := procNetDevInterfaceRE.FindStringSubmatch(line)
|
||||
|
@ -79,14 +80,26 @@ func parseNetDevStats(r io.Reader, ignore *regexp.Regexp, accept *regexp.Regexp,
|
|||
return nil, fmt.Errorf("couldn't get values, invalid line in net/dev: %q", parts[2])
|
||||
}
|
||||
|
||||
netDev[dev] = map[string]string{}
|
||||
devStats := map[string]uint64{}
|
||||
addStats := func(key, value string) {
|
||||
v, err := strconv.ParseUint(value, 0, 64)
|
||||
if err != nil {
|
||||
level.Debug(logger).Log("msg", "invalid value in netstats", "key", key, "value", value, "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
devStats[key] = v
|
||||
}
|
||||
|
||||
for i := 0; i < len(receiveHeader); i++ {
|
||||
netDev[dev]["receive_"+receiveHeader[i]] = values[i]
|
||||
addStats("receive_"+receiveHeader[i], values[i])
|
||||
}
|
||||
|
||||
for i := 0; i < len(transmitHeader); i++ {
|
||||
netDev[dev]["transmit_"+transmitHeader[i]] = values[i+len(receiveHeader)]
|
||||
addStats("transmit_"+transmitHeader[i], values[i+len(receiveHeader)])
|
||||
}
|
||||
|
||||
netDev[dev] = devStats
|
||||
}
|
||||
return netDev, scanner.Err()
|
||||
}
|
||||
|
|
|
@ -32,16 +32,16 @@ func TestNetDevStatsIgnore(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if want, got := "10437182923", netStats["wlan0"]["receive_bytes"]; want != got {
|
||||
t.Errorf("want netstat wlan0 bytes %s, got %s", want, got)
|
||||
if want, got := uint64(10437182923), netStats["wlan0"]["receive_bytes"]; want != got {
|
||||
t.Errorf("want netstat wlan0 bytes %v, got %v", want, got)
|
||||
}
|
||||
|
||||
if want, got := "68210035552", netStats["eth0"]["receive_bytes"]; want != got {
|
||||
t.Errorf("want netstat eth0 bytes %s, got %s", want, got)
|
||||
if want, got := uint64(68210035552), netStats["eth0"]["receive_bytes"]; want != got {
|
||||
t.Errorf("want netstat eth0 bytes %v, got %v", want, got)
|
||||
}
|
||||
|
||||
if want, got := "934", netStats["tun0"]["transmit_packets"]; want != got {
|
||||
t.Errorf("want netstat tun0 packets %s, got %s", want, got)
|
||||
if want, got := uint64(934), netStats["tun0"]["transmit_packets"]; want != got {
|
||||
t.Errorf("want netstat tun0 packets %v, got %v", want, got)
|
||||
}
|
||||
|
||||
if want, got := 9, len(netStats); want != got {
|
||||
|
@ -52,11 +52,11 @@ func TestNetDevStatsIgnore(t *testing.T) {
|
|||
t.Error("want fixture interface veth4B09XN to not exist, but it does")
|
||||
}
|
||||
|
||||
if want, got := "0", netStats["ibr10:30"]["receive_fifo"]; want != got {
|
||||
if want, got := uint64(0), netStats["ibr10:30"]["receive_fifo"]; want != got {
|
||||
t.Error("want fixture interface ibr10:30 to exist, but it does not")
|
||||
}
|
||||
|
||||
if want, got := "72", netStats["💩0"]["receive_multicast"]; want != got {
|
||||
if want, got := uint64(72), netStats["💩0"]["receive_multicast"]; want != got {
|
||||
t.Error("want fixture interface 💩0 to exist, but it does not")
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ func TestNetDevStatsAccept(t *testing.T) {
|
|||
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 {
|
||||
if want, got := uint64(72), netStats["💩0"]["receive_multicast"]; want != got {
|
||||
t.Error("want fixture interface 💩0 to exist, but it does not")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ package collector
|
|||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/log/level"
|
||||
|
@ -32,8 +31,8 @@ import (
|
|||
*/
|
||||
import "C"
|
||||
|
||||
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (map[string]map[string]string, error) {
|
||||
netDev := map[string]map[string]string{}
|
||||
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (netDevStats, error) {
|
||||
netDev := netDevStats{}
|
||||
|
||||
var ifap, ifa *C.struct_ifaddrs
|
||||
if C.getifaddrs(&ifap) == -1 {
|
||||
|
@ -42,30 +41,32 @@ func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Log
|
|||
defer C.freeifaddrs(ifap)
|
||||
|
||||
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 != nil && ignore.MatchString(dev) {
|
||||
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
|
||||
continue
|
||||
}
|
||||
if accept != nil && !accept.MatchString(dev) {
|
||||
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
|
||||
continue
|
||||
}
|
||||
if ifa.ifa_addr.sa_family != C.AF_LINK {
|
||||
continue
|
||||
}
|
||||
|
||||
devStats := map[string]string{}
|
||||
data := (*C.struct_if_data)(ifa.ifa_data)
|
||||
dev := C.GoString(ifa.ifa_name)
|
||||
if ignore != nil && ignore.MatchString(dev) {
|
||||
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
|
||||
continue
|
||||
}
|
||||
if accept != nil && !accept.MatchString(dev) {
|
||||
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
|
||||
continue
|
||||
}
|
||||
|
||||
devStats["receive_packets"] = strconv.Itoa(int(data.ifi_ipackets))
|
||||
devStats["transmit_packets"] = strconv.Itoa(int(data.ifi_opackets))
|
||||
devStats["receive_errs"] = strconv.Itoa(int(data.ifi_ierrors))
|
||||
devStats["transmit_errs"] = strconv.Itoa(int(data.ifi_oerrors))
|
||||
devStats["receive_bytes"] = strconv.Itoa(int(data.ifi_ibytes))
|
||||
devStats["transmit_bytes"] = strconv.Itoa(int(data.ifi_obytes))
|
||||
devStats["receive_multicast"] = strconv.Itoa(int(data.ifi_imcasts))
|
||||
devStats["transmit_multicast"] = strconv.Itoa(int(data.ifi_omcasts))
|
||||
devStats["receive_drop"] = strconv.Itoa(int(data.ifi_iqdrops))
|
||||
netDev[dev] = devStats
|
||||
data := (*C.struct_if_data)(ifa.ifa_data)
|
||||
|
||||
netDev[dev] = map[string]uint64{
|
||||
"receive_packets": uint64(data.ifi_ipackets),
|
||||
"transmit_packets": uint64(data.ifi_opackets),
|
||||
"receive_errs": uint64(data.ifi_ierrors),
|
||||
"transmit_errs": uint64(data.ifi_oerrors),
|
||||
"receive_bytes": uint64(data.ifi_ibytes),
|
||||
"transmit_bytes": uint64(data.ifi_obytes),
|
||||
"receive_multicast": uint64(data.ifi_imcasts),
|
||||
"transmit_multicast": uint64(data.ifi_omcasts),
|
||||
"receive_drop": uint64(data.ifi_iqdrops),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue