diff --git a/collector/netdev_bsd.go b/collector/netdev_bsd.go index 8bed2e14..fd8d9a91 100644 --- a/collector/netdev_bsd.go +++ b/collector/netdev_bsd.go @@ -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) -} diff --git a/collector/netdev_bsd_test.go b/collector/netdev_bsd_test.go deleted file mode 100644 index a661c1cc..00000000 --- a/collector/netdev_bsd_test.go +++ /dev/null @@ -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) - } - } -} diff --git a/collector/netdev_common.go b/collector/netdev_common.go index a28bd43b..7b54c472 100644 --- a/collector/netdev_common.go +++ b/collector/netdev_common.go @@ -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 diff --git a/collector/netdev_darwin.go b/collector/netdev_darwin.go index 4970853f..cd1e01c7 100644 --- a/collector/netdev_darwin.go +++ b/collector/netdev_darwin.go @@ -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 diff --git a/collector/netdev_linux.go b/collector/netdev_linux.go index 1a4b5dfc..ac582729 100644 --- a/collector/netdev_linux.go +++ b/collector/netdev_linux.go @@ -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() } diff --git a/collector/netdev_linux_test.go b/collector/netdev_linux_test.go index 1c88d83c..259bbfeb 100644 --- a/collector/netdev_linux_test.go +++ b/collector/netdev_linux_test.go @@ -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") } } diff --git a/collector/netdev_openbsd.go b/collector/netdev_openbsd.go index f7c90309..87ee921f 100644 --- a/collector/netdev_openbsd.go +++ b/collector/netdev_openbsd.go @@ -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), } }