From f23a956c4fece3bd454925a40e598bab44f4fd76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Knecht?= Date: Wed, 7 Jul 2021 11:05:06 +0200 Subject: [PATCH 1/4] collector/netdev_linux.go: Use netlink to get stats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of parsing `/proc/net/dev` to get network interface statistics, get them from a netlink call. Internally, both come from the [rtnl_link_stats64] struct, but with `/proc/net/dev`, some of the values are aggregated together in [dev_seq_printf_stats], so we get less information out of them. This commit maintains compatibility by aggregating those stats back into the same metrics. [rtnl_link_stats64]: https://github.com/torvalds/linux/blob/master/include/uapi/linux/if_link.h#L42-L246 [dev_seq_printf_stats]: https://github.com/torvalds/linux/blob/master/net/core/net-procfs.c#L75-L97 Signed-off-by: Benoรฎt Knecht --- collector/netdev_linux.go | 100 +++++++++---------------- collector/netdev_linux_test.go | 133 +++++++++++++++++++++++++++------ 2 files changed, 149 insertions(+), 84 deletions(-) diff --git a/collector/netdev_linux.go b/collector/netdev_linux.go index baf7f4eb..5a0d5c34 100644 --- a/collector/netdev_linux.go +++ b/collector/netdev_linux.go @@ -17,86 +17,60 @@ package collector import ( - "bufio" - "fmt" - "io" - "os" - "regexp" - "strconv" - "strings" - "github.com/go-kit/log" "github.com/go-kit/log/level" -) -var ( - procNetDevInterfaceRE = regexp.MustCompile(`^(.+): *(.+)$`) - procNetDevFieldSep = regexp.MustCompile(` +`) + "github.com/jsimonetti/rtnetlink" ) func getNetDevStats(filter *deviceFilter, logger log.Logger) (netDevStats, error) { - file, err := os.Open(procFilePath("net/dev")) + conn, err := rtnetlink.Dial(nil) if err != nil { return nil, err } - defer file.Close() + defer conn.Close() - return parseNetDevStats(file, filter, logger) -} - -func parseNetDevStats(r io.Reader, filter *deviceFilter, logger log.Logger) (netDevStats, error) { - scanner := bufio.NewScanner(r) - scanner.Scan() // skip first header - scanner.Scan() - parts := strings.Split(scanner.Text(), "|") - if len(parts) != 3 { // interface + receive + transmit - return nil, fmt.Errorf("invalid header line in net/dev: %s", - scanner.Text()) + links, err := conn.Link.List() + if err != nil { + return nil, err } - receiveHeader := strings.Fields(parts[1]) - transmitHeader := strings.Fields(parts[2]) - headerLength := len(receiveHeader) + len(transmitHeader) + return netlinkStats(links, filter, logger), nil +} - netDev := netDevStats{} - for scanner.Scan() { - line := strings.TrimLeft(scanner.Text(), " ") - parts := procNetDevInterfaceRE.FindStringSubmatch(line) - if len(parts) != 3 { - return nil, fmt.Errorf("couldn't get interface name, invalid line in net/dev: %q", line) - } +func netlinkStats(links []rtnetlink.LinkMessage, filter *deviceFilter, logger log.Logger) netDevStats { + metrics := netDevStats{} - dev := parts[1] - if filter.ignored(dev) { - level.Debug(logger).Log("msg", "Ignoring device", "device", dev) + for _, msg := range links { + name := msg.Attributes.Name + stats := msg.Attributes.Stats64 + + if filter.ignored(name) { + level.Debug(logger).Log("msg", "Ignoring device", "device", name) continue } - values := procNetDevFieldSep.Split(strings.TrimLeft(parts[2], " "), -1) - if len(values) != headerLength { - return nil, fmt.Errorf("couldn't get values, invalid line in net/dev: %q", parts[2]) + // https://github.com/torvalds/linux/blob/master/include/uapi/linux/if_link.h#L42-L246 + // https://github.com/torvalds/linux/blob/master/net/core/net-procfs.c#L75-L97 + metrics[name] = map[string]uint64{ + "receive_packets": stats.RXPackets, + "transmit_packets": stats.TXPackets, + "receive_bytes": stats.RXBytes, + "transmit_bytes": stats.TXBytes, + "receive_errs": stats.RXErrors, + "transmit_errs": stats.TXErrors, + "receive_drop": stats.RXDropped + stats.RXMissedErrors, + "transmit_drop": stats.TXDropped, + "receive_multicast": stats.Multicast, + "transmit_colls": stats.Collisions, + "receive_frame": stats.RXLengthErrors + stats.RXOverErrors + stats.RXCRCErrors + stats.RXFrameErrors, + "receive_fifo": stats.RXFIFOErrors, + "transmit_carrier": stats.TXAbortedErrors + stats.TXCarrierErrors + stats.TXHeartbeatErrors + stats.TXWindowErrors, + "transmit_fifo": stats.TXFIFOErrors, + "receive_compressed": stats.RXCompressed, + "transmit_compressed": stats.TXCompressed, } - - 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++ { - addStats("receive_"+receiveHeader[i], values[i]) - } - - for i := 0; i < len(transmitHeader); i++ { - addStats("transmit_"+transmitHeader[i], values[i+len(receiveHeader)]) - } - - netDev[dev] = devStats } - return netDev, scanner.Err() + + return metrics } diff --git a/collector/netdev_linux_test.go b/collector/netdev_linux_test.go index 14935df6..8dae9aa3 100644 --- a/collector/netdev_linux_test.go +++ b/collector/netdev_linux_test.go @@ -14,25 +14,125 @@ package collector import ( - "os" "testing" "github.com/go-kit/log" + + "github.com/jsimonetti/rtnetlink" ) -func TestNetDevStatsIgnore(t *testing.T) { - file, err := os.Open("fixtures/proc/net/dev") - if err != nil { - t.Fatal(err) - } - defer file.Close() +var links = []rtnetlink.LinkMessage{ + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "tun0", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 24, + TXPackets: 934, + RXBytes: 1888, + TXBytes: 67120, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "veth4B09XN", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 8, + TXPackets: 10640, + RXBytes: 648, + TXBytes: 1943284, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "lo", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 1832522, + TXPackets: 1832522, + RXBytes: 435303245, + TXBytes: 435303245, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "eth0", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 520993275, + TXPackets: 43451486, + RXBytes: 68210035552, + TXBytes: 9315587528, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "lxcbr0", + Stats64: &rtnetlink.LinkStats64{ + TXPackets: 28339, + TXBytes: 2630299, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "wlan0", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 13899359, + TXPackets: 11726200, + RXBytes: 10437182923, + TXBytes: 2851649360, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "docker0", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 1065585, + TXPackets: 1929779, + RXBytes: 64910168, + TXBytes: 2681662018, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "ibr10:30", + Stats64: &rtnetlink.LinkStats64{}, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "flannel.1", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 228499337, + TXPackets: 258369223, + RXBytes: 18144009813, + TXBytes: 20758990068, + TXDropped: 64, + }, + }, + }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "๐Ÿ’ฉ0", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 105557, + TXPackets: 304261, + RXBytes: 57750104, + TXBytes: 404570255, + Multicast: 72, + }, + }, + }, +} +func TestNetDevStatsIgnore(t *testing.T) { filter := newDeviceFilter("^veth", "") - netStats, err := parseNetDevStats(file, &filter, log.NewNopLogger()) - if err != nil { - t.Fatal(err) - } + netStats := netlinkStats(links, &filter, log.NewNopLogger()) if want, got := uint64(10437182923), netStats["wlan0"]["receive_bytes"]; want != got { t.Errorf("want netstat wlan0 bytes %v, got %v", want, got) @@ -64,17 +164,8 @@ func TestNetDevStatsIgnore(t *testing.T) { } func TestNetDevStatsAccept(t *testing.T) { - file, err := os.Open("fixtures/proc/net/dev") - if err != nil { - t.Fatal(err) - } - defer file.Close() - filter := newDeviceFilter("", "^๐Ÿ’ฉ0$") - netStats, err := parseNetDevStats(file, &filter, log.NewNopLogger()) - if err != nil { - t.Fatal(err) - } + netStats := netlinkStats(links, &filter, log.NewNopLogger()) if want, got := 1, len(netStats); want != got { t.Errorf("want count of devices to be %d, got %d", want, got) From a71d0bddc8a143a5fcdc17bca706470ddabed3bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Knecht?= Date: Tue, 20 Jul 2021 13:47:08 +0200 Subject: [PATCH 2/4] end-to-end-test.sh: Fix netdev metrics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since netdev metrics are now read from netlink instead of `/proc/net/dev`, we can't easily spoof them for the end-to-end tests by reading a fixture file in place of `/proc/net/dev`. Therefore, we only get metrics for `lo` and ignore those that would return unpredictable values (i.e. the byte and packet counters). Signed-off-by: Benoรฎt Knecht --- collector/fixtures/e2e-64k-page-output.txt | 151 +-------------------- collector/fixtures/e2e-output.txt | 151 +-------------------- collector/fixtures/proc/net/dev | 12 -- end-to-end-test.sh | 3 +- 4 files changed, 8 insertions(+), 309 deletions(-) delete mode 100644 collector/fixtures/proc/net/dev diff --git a/collector/fixtures/e2e-64k-page-output.txt b/collector/fixtures/e2e-64k-page-output.txt index 7e0ef4c6..1bbb9894 100644 --- a/collector/fixtures/e2e-64k-page-output.txt +++ b/collector/fixtures/e2e-64k-page-output.txt @@ -2414,199 +2414,54 @@ node_network_protocol_type{device="bond0"} 1 node_network_protocol_type{device="eth0"} 1 # HELP node_network_receive_bytes_total Network device statistic receive_bytes. # TYPE node_network_receive_bytes_total counter -node_network_receive_bytes_total{device="docker0"} 6.4910168e+07 -node_network_receive_bytes_total{device="eth0"} 6.8210035552e+10 -node_network_receive_bytes_total{device="flannel.1"} 1.8144009813e+10 -node_network_receive_bytes_total{device="ibr10:30"} 0 -node_network_receive_bytes_total{device="lo"} 4.35303245e+08 -node_network_receive_bytes_total{device="lxcbr0"} 0 -node_network_receive_bytes_total{device="tun0"} 1888 -node_network_receive_bytes_total{device="veth4B09XN"} 648 -node_network_receive_bytes_total{device="wlan0"} 1.0437182923e+10 -node_network_receive_bytes_total{device="๐Ÿ’ฉ0"} 5.7750104e+07 # HELP node_network_receive_compressed_total Network device statistic receive_compressed. # TYPE node_network_receive_compressed_total counter -node_network_receive_compressed_total{device="docker0"} 0 -node_network_receive_compressed_total{device="eth0"} 0 -node_network_receive_compressed_total{device="flannel.1"} 0 -node_network_receive_compressed_total{device="ibr10:30"} 0 node_network_receive_compressed_total{device="lo"} 0 -node_network_receive_compressed_total{device="lxcbr0"} 0 -node_network_receive_compressed_total{device="tun0"} 0 -node_network_receive_compressed_total{device="veth4B09XN"} 0 -node_network_receive_compressed_total{device="wlan0"} 0 -node_network_receive_compressed_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_receive_drop_total Network device statistic receive_drop. # TYPE node_network_receive_drop_total counter -node_network_receive_drop_total{device="docker0"} 0 -node_network_receive_drop_total{device="eth0"} 0 -node_network_receive_drop_total{device="flannel.1"} 0 -node_network_receive_drop_total{device="ibr10:30"} 0 node_network_receive_drop_total{device="lo"} 0 -node_network_receive_drop_total{device="lxcbr0"} 0 -node_network_receive_drop_total{device="tun0"} 0 -node_network_receive_drop_total{device="veth4B09XN"} 0 -node_network_receive_drop_total{device="wlan0"} 0 -node_network_receive_drop_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_receive_errs_total Network device statistic receive_errs. # TYPE node_network_receive_errs_total counter -node_network_receive_errs_total{device="docker0"} 0 -node_network_receive_errs_total{device="eth0"} 0 -node_network_receive_errs_total{device="flannel.1"} 0 -node_network_receive_errs_total{device="ibr10:30"} 0 node_network_receive_errs_total{device="lo"} 0 -node_network_receive_errs_total{device="lxcbr0"} 0 -node_network_receive_errs_total{device="tun0"} 0 -node_network_receive_errs_total{device="veth4B09XN"} 0 -node_network_receive_errs_total{device="wlan0"} 0 -node_network_receive_errs_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_receive_fifo_total Network device statistic receive_fifo. # TYPE node_network_receive_fifo_total counter -node_network_receive_fifo_total{device="docker0"} 0 -node_network_receive_fifo_total{device="eth0"} 0 -node_network_receive_fifo_total{device="flannel.1"} 0 -node_network_receive_fifo_total{device="ibr10:30"} 0 node_network_receive_fifo_total{device="lo"} 0 -node_network_receive_fifo_total{device="lxcbr0"} 0 -node_network_receive_fifo_total{device="tun0"} 0 -node_network_receive_fifo_total{device="veth4B09XN"} 0 -node_network_receive_fifo_total{device="wlan0"} 0 -node_network_receive_fifo_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_receive_frame_total Network device statistic receive_frame. # TYPE node_network_receive_frame_total counter -node_network_receive_frame_total{device="docker0"} 0 -node_network_receive_frame_total{device="eth0"} 0 -node_network_receive_frame_total{device="flannel.1"} 0 -node_network_receive_frame_total{device="ibr10:30"} 0 node_network_receive_frame_total{device="lo"} 0 -node_network_receive_frame_total{device="lxcbr0"} 0 -node_network_receive_frame_total{device="tun0"} 0 -node_network_receive_frame_total{device="veth4B09XN"} 0 -node_network_receive_frame_total{device="wlan0"} 0 -node_network_receive_frame_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_receive_multicast_total Network device statistic receive_multicast. # TYPE node_network_receive_multicast_total counter -node_network_receive_multicast_total{device="docker0"} 0 -node_network_receive_multicast_total{device="eth0"} 0 -node_network_receive_multicast_total{device="flannel.1"} 0 -node_network_receive_multicast_total{device="ibr10:30"} 0 node_network_receive_multicast_total{device="lo"} 0 -node_network_receive_multicast_total{device="lxcbr0"} 0 -node_network_receive_multicast_total{device="tun0"} 0 -node_network_receive_multicast_total{device="veth4B09XN"} 0 -node_network_receive_multicast_total{device="wlan0"} 0 -node_network_receive_multicast_total{device="๐Ÿ’ฉ0"} 72 +# HELP node_network_receive_nohandler_total Network device statistic receive_nohandler. +# TYPE node_network_receive_nohandler_total counter +node_network_receive_nohandler_total{device="lo"} 0 # HELP node_network_receive_packets_total Network device statistic receive_packets. # TYPE node_network_receive_packets_total counter -node_network_receive_packets_total{device="docker0"} 1.065585e+06 -node_network_receive_packets_total{device="eth0"} 5.20993275e+08 -node_network_receive_packets_total{device="flannel.1"} 2.28499337e+08 -node_network_receive_packets_total{device="ibr10:30"} 0 -node_network_receive_packets_total{device="lo"} 1.832522e+06 -node_network_receive_packets_total{device="lxcbr0"} 0 -node_network_receive_packets_total{device="tun0"} 24 -node_network_receive_packets_total{device="veth4B09XN"} 8 -node_network_receive_packets_total{device="wlan0"} 1.3899359e+07 -node_network_receive_packets_total{device="๐Ÿ’ฉ0"} 105557 # HELP node_network_speed_bytes speed_bytes value of /sys/class/net/. # TYPE node_network_speed_bytes gauge node_network_speed_bytes{device="eth0"} 1.25e+08 # HELP node_network_transmit_bytes_total Network device statistic transmit_bytes. # TYPE node_network_transmit_bytes_total counter -node_network_transmit_bytes_total{device="docker0"} 2.681662018e+09 -node_network_transmit_bytes_total{device="eth0"} 9.315587528e+09 -node_network_transmit_bytes_total{device="flannel.1"} 2.0758990068e+10 -node_network_transmit_bytes_total{device="ibr10:30"} 0 -node_network_transmit_bytes_total{device="lo"} 4.35303245e+08 -node_network_transmit_bytes_total{device="lxcbr0"} 2.630299e+06 -node_network_transmit_bytes_total{device="tun0"} 67120 -node_network_transmit_bytes_total{device="veth4B09XN"} 1.943284e+06 -node_network_transmit_bytes_total{device="wlan0"} 2.85164936e+09 -node_network_transmit_bytes_total{device="๐Ÿ’ฉ0"} 4.04570255e+08 # HELP node_network_transmit_carrier_total Network device statistic transmit_carrier. # TYPE node_network_transmit_carrier_total counter -node_network_transmit_carrier_total{device="docker0"} 0 -node_network_transmit_carrier_total{device="eth0"} 0 -node_network_transmit_carrier_total{device="flannel.1"} 0 -node_network_transmit_carrier_total{device="ibr10:30"} 0 node_network_transmit_carrier_total{device="lo"} 0 -node_network_transmit_carrier_total{device="lxcbr0"} 0 -node_network_transmit_carrier_total{device="tun0"} 0 -node_network_transmit_carrier_total{device="veth4B09XN"} 0 -node_network_transmit_carrier_total{device="wlan0"} 0 -node_network_transmit_carrier_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_transmit_colls_total Network device statistic transmit_colls. # TYPE node_network_transmit_colls_total counter -node_network_transmit_colls_total{device="docker0"} 0 -node_network_transmit_colls_total{device="eth0"} 0 -node_network_transmit_colls_total{device="flannel.1"} 0 -node_network_transmit_colls_total{device="ibr10:30"} 0 node_network_transmit_colls_total{device="lo"} 0 -node_network_transmit_colls_total{device="lxcbr0"} 0 -node_network_transmit_colls_total{device="tun0"} 0 -node_network_transmit_colls_total{device="veth4B09XN"} 0 -node_network_transmit_colls_total{device="wlan0"} 0 -node_network_transmit_colls_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_transmit_compressed_total Network device statistic transmit_compressed. # TYPE node_network_transmit_compressed_total counter -node_network_transmit_compressed_total{device="docker0"} 0 -node_network_transmit_compressed_total{device="eth0"} 0 -node_network_transmit_compressed_total{device="flannel.1"} 0 -node_network_transmit_compressed_total{device="ibr10:30"} 0 node_network_transmit_compressed_total{device="lo"} 0 -node_network_transmit_compressed_total{device="lxcbr0"} 0 -node_network_transmit_compressed_total{device="tun0"} 0 -node_network_transmit_compressed_total{device="veth4B09XN"} 0 -node_network_transmit_compressed_total{device="wlan0"} 0 -node_network_transmit_compressed_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_transmit_drop_total Network device statistic transmit_drop. # TYPE node_network_transmit_drop_total counter -node_network_transmit_drop_total{device="docker0"} 0 -node_network_transmit_drop_total{device="eth0"} 0 -node_network_transmit_drop_total{device="flannel.1"} 64 -node_network_transmit_drop_total{device="ibr10:30"} 0 node_network_transmit_drop_total{device="lo"} 0 -node_network_transmit_drop_total{device="lxcbr0"} 0 -node_network_transmit_drop_total{device="tun0"} 0 -node_network_transmit_drop_total{device="veth4B09XN"} 0 -node_network_transmit_drop_total{device="wlan0"} 0 -node_network_transmit_drop_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_transmit_errs_total Network device statistic transmit_errs. # TYPE node_network_transmit_errs_total counter -node_network_transmit_errs_total{device="docker0"} 0 -node_network_transmit_errs_total{device="eth0"} 0 -node_network_transmit_errs_total{device="flannel.1"} 0 -node_network_transmit_errs_total{device="ibr10:30"} 0 node_network_transmit_errs_total{device="lo"} 0 -node_network_transmit_errs_total{device="lxcbr0"} 0 -node_network_transmit_errs_total{device="tun0"} 0 -node_network_transmit_errs_total{device="veth4B09XN"} 0 -node_network_transmit_errs_total{device="wlan0"} 0 -node_network_transmit_errs_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_transmit_fifo_total Network device statistic transmit_fifo. # TYPE node_network_transmit_fifo_total counter -node_network_transmit_fifo_total{device="docker0"} 0 -node_network_transmit_fifo_total{device="eth0"} 0 -node_network_transmit_fifo_total{device="flannel.1"} 0 -node_network_transmit_fifo_total{device="ibr10:30"} 0 node_network_transmit_fifo_total{device="lo"} 0 -node_network_transmit_fifo_total{device="lxcbr0"} 0 -node_network_transmit_fifo_total{device="tun0"} 0 -node_network_transmit_fifo_total{device="veth4B09XN"} 0 -node_network_transmit_fifo_total{device="wlan0"} 0 -node_network_transmit_fifo_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_transmit_packets_total Network device statistic transmit_packets. # TYPE node_network_transmit_packets_total counter -node_network_transmit_packets_total{device="docker0"} 1.929779e+06 -node_network_transmit_packets_total{device="eth0"} 4.3451486e+07 -node_network_transmit_packets_total{device="flannel.1"} 2.58369223e+08 -node_network_transmit_packets_total{device="ibr10:30"} 0 -node_network_transmit_packets_total{device="lo"} 1.832522e+06 -node_network_transmit_packets_total{device="lxcbr0"} 28339 -node_network_transmit_packets_total{device="tun0"} 934 -node_network_transmit_packets_total{device="veth4B09XN"} 10640 -node_network_transmit_packets_total{device="wlan0"} 1.17262e+07 -node_network_transmit_packets_total{device="๐Ÿ’ฉ0"} 304261 # HELP node_network_transmit_queue_length transmit_queue_length value of /sys/class/net/. # TYPE node_network_transmit_queue_length gauge node_network_transmit_queue_length{device="bond0"} 1000 diff --git a/collector/fixtures/e2e-output.txt b/collector/fixtures/e2e-output.txt index 97c899ac..5c15de28 100644 --- a/collector/fixtures/e2e-output.txt +++ b/collector/fixtures/e2e-output.txt @@ -2436,199 +2436,54 @@ node_network_protocol_type{device="bond0"} 1 node_network_protocol_type{device="eth0"} 1 # HELP node_network_receive_bytes_total Network device statistic receive_bytes. # TYPE node_network_receive_bytes_total counter -node_network_receive_bytes_total{device="docker0"} 6.4910168e+07 -node_network_receive_bytes_total{device="eth0"} 6.8210035552e+10 -node_network_receive_bytes_total{device="flannel.1"} 1.8144009813e+10 -node_network_receive_bytes_total{device="ibr10:30"} 0 -node_network_receive_bytes_total{device="lo"} 4.35303245e+08 -node_network_receive_bytes_total{device="lxcbr0"} 0 -node_network_receive_bytes_total{device="tun0"} 1888 -node_network_receive_bytes_total{device="veth4B09XN"} 648 -node_network_receive_bytes_total{device="wlan0"} 1.0437182923e+10 -node_network_receive_bytes_total{device="๐Ÿ’ฉ0"} 5.7750104e+07 # HELP node_network_receive_compressed_total Network device statistic receive_compressed. # TYPE node_network_receive_compressed_total counter -node_network_receive_compressed_total{device="docker0"} 0 -node_network_receive_compressed_total{device="eth0"} 0 -node_network_receive_compressed_total{device="flannel.1"} 0 -node_network_receive_compressed_total{device="ibr10:30"} 0 node_network_receive_compressed_total{device="lo"} 0 -node_network_receive_compressed_total{device="lxcbr0"} 0 -node_network_receive_compressed_total{device="tun0"} 0 -node_network_receive_compressed_total{device="veth4B09XN"} 0 -node_network_receive_compressed_total{device="wlan0"} 0 -node_network_receive_compressed_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_receive_drop_total Network device statistic receive_drop. # TYPE node_network_receive_drop_total counter -node_network_receive_drop_total{device="docker0"} 0 -node_network_receive_drop_total{device="eth0"} 0 -node_network_receive_drop_total{device="flannel.1"} 0 -node_network_receive_drop_total{device="ibr10:30"} 0 node_network_receive_drop_total{device="lo"} 0 -node_network_receive_drop_total{device="lxcbr0"} 0 -node_network_receive_drop_total{device="tun0"} 0 -node_network_receive_drop_total{device="veth4B09XN"} 0 -node_network_receive_drop_total{device="wlan0"} 0 -node_network_receive_drop_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_receive_errs_total Network device statistic receive_errs. # TYPE node_network_receive_errs_total counter -node_network_receive_errs_total{device="docker0"} 0 -node_network_receive_errs_total{device="eth0"} 0 -node_network_receive_errs_total{device="flannel.1"} 0 -node_network_receive_errs_total{device="ibr10:30"} 0 node_network_receive_errs_total{device="lo"} 0 -node_network_receive_errs_total{device="lxcbr0"} 0 -node_network_receive_errs_total{device="tun0"} 0 -node_network_receive_errs_total{device="veth4B09XN"} 0 -node_network_receive_errs_total{device="wlan0"} 0 -node_network_receive_errs_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_receive_fifo_total Network device statistic receive_fifo. # TYPE node_network_receive_fifo_total counter -node_network_receive_fifo_total{device="docker0"} 0 -node_network_receive_fifo_total{device="eth0"} 0 -node_network_receive_fifo_total{device="flannel.1"} 0 -node_network_receive_fifo_total{device="ibr10:30"} 0 node_network_receive_fifo_total{device="lo"} 0 -node_network_receive_fifo_total{device="lxcbr0"} 0 -node_network_receive_fifo_total{device="tun0"} 0 -node_network_receive_fifo_total{device="veth4B09XN"} 0 -node_network_receive_fifo_total{device="wlan0"} 0 -node_network_receive_fifo_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_receive_frame_total Network device statistic receive_frame. # TYPE node_network_receive_frame_total counter -node_network_receive_frame_total{device="docker0"} 0 -node_network_receive_frame_total{device="eth0"} 0 -node_network_receive_frame_total{device="flannel.1"} 0 -node_network_receive_frame_total{device="ibr10:30"} 0 node_network_receive_frame_total{device="lo"} 0 -node_network_receive_frame_total{device="lxcbr0"} 0 -node_network_receive_frame_total{device="tun0"} 0 -node_network_receive_frame_total{device="veth4B09XN"} 0 -node_network_receive_frame_total{device="wlan0"} 0 -node_network_receive_frame_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_receive_multicast_total Network device statistic receive_multicast. # TYPE node_network_receive_multicast_total counter -node_network_receive_multicast_total{device="docker0"} 0 -node_network_receive_multicast_total{device="eth0"} 0 -node_network_receive_multicast_total{device="flannel.1"} 0 -node_network_receive_multicast_total{device="ibr10:30"} 0 node_network_receive_multicast_total{device="lo"} 0 -node_network_receive_multicast_total{device="lxcbr0"} 0 -node_network_receive_multicast_total{device="tun0"} 0 -node_network_receive_multicast_total{device="veth4B09XN"} 0 -node_network_receive_multicast_total{device="wlan0"} 0 -node_network_receive_multicast_total{device="๐Ÿ’ฉ0"} 72 +# HELP node_network_receive_nohandler_total Network device statistic receive_nohandler. +# TYPE node_network_receive_nohandler_total counter +node_network_receive_nohandler_total{device="lo"} 0 # HELP node_network_receive_packets_total Network device statistic receive_packets. # TYPE node_network_receive_packets_total counter -node_network_receive_packets_total{device="docker0"} 1.065585e+06 -node_network_receive_packets_total{device="eth0"} 5.20993275e+08 -node_network_receive_packets_total{device="flannel.1"} 2.28499337e+08 -node_network_receive_packets_total{device="ibr10:30"} 0 -node_network_receive_packets_total{device="lo"} 1.832522e+06 -node_network_receive_packets_total{device="lxcbr0"} 0 -node_network_receive_packets_total{device="tun0"} 24 -node_network_receive_packets_total{device="veth4B09XN"} 8 -node_network_receive_packets_total{device="wlan0"} 1.3899359e+07 -node_network_receive_packets_total{device="๐Ÿ’ฉ0"} 105557 # HELP node_network_speed_bytes speed_bytes value of /sys/class/net/. # TYPE node_network_speed_bytes gauge node_network_speed_bytes{device="eth0"} 1.25e+08 # HELP node_network_transmit_bytes_total Network device statistic transmit_bytes. # TYPE node_network_transmit_bytes_total counter -node_network_transmit_bytes_total{device="docker0"} 2.681662018e+09 -node_network_transmit_bytes_total{device="eth0"} 9.315587528e+09 -node_network_transmit_bytes_total{device="flannel.1"} 2.0758990068e+10 -node_network_transmit_bytes_total{device="ibr10:30"} 0 -node_network_transmit_bytes_total{device="lo"} 4.35303245e+08 -node_network_transmit_bytes_total{device="lxcbr0"} 2.630299e+06 -node_network_transmit_bytes_total{device="tun0"} 67120 -node_network_transmit_bytes_total{device="veth4B09XN"} 1.943284e+06 -node_network_transmit_bytes_total{device="wlan0"} 2.85164936e+09 -node_network_transmit_bytes_total{device="๐Ÿ’ฉ0"} 4.04570255e+08 # HELP node_network_transmit_carrier_total Network device statistic transmit_carrier. # TYPE node_network_transmit_carrier_total counter -node_network_transmit_carrier_total{device="docker0"} 0 -node_network_transmit_carrier_total{device="eth0"} 0 -node_network_transmit_carrier_total{device="flannel.1"} 0 -node_network_transmit_carrier_total{device="ibr10:30"} 0 node_network_transmit_carrier_total{device="lo"} 0 -node_network_transmit_carrier_total{device="lxcbr0"} 0 -node_network_transmit_carrier_total{device="tun0"} 0 -node_network_transmit_carrier_total{device="veth4B09XN"} 0 -node_network_transmit_carrier_total{device="wlan0"} 0 -node_network_transmit_carrier_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_transmit_colls_total Network device statistic transmit_colls. # TYPE node_network_transmit_colls_total counter -node_network_transmit_colls_total{device="docker0"} 0 -node_network_transmit_colls_total{device="eth0"} 0 -node_network_transmit_colls_total{device="flannel.1"} 0 -node_network_transmit_colls_total{device="ibr10:30"} 0 node_network_transmit_colls_total{device="lo"} 0 -node_network_transmit_colls_total{device="lxcbr0"} 0 -node_network_transmit_colls_total{device="tun0"} 0 -node_network_transmit_colls_total{device="veth4B09XN"} 0 -node_network_transmit_colls_total{device="wlan0"} 0 -node_network_transmit_colls_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_transmit_compressed_total Network device statistic transmit_compressed. # TYPE node_network_transmit_compressed_total counter -node_network_transmit_compressed_total{device="docker0"} 0 -node_network_transmit_compressed_total{device="eth0"} 0 -node_network_transmit_compressed_total{device="flannel.1"} 0 -node_network_transmit_compressed_total{device="ibr10:30"} 0 node_network_transmit_compressed_total{device="lo"} 0 -node_network_transmit_compressed_total{device="lxcbr0"} 0 -node_network_transmit_compressed_total{device="tun0"} 0 -node_network_transmit_compressed_total{device="veth4B09XN"} 0 -node_network_transmit_compressed_total{device="wlan0"} 0 -node_network_transmit_compressed_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_transmit_drop_total Network device statistic transmit_drop. # TYPE node_network_transmit_drop_total counter -node_network_transmit_drop_total{device="docker0"} 0 -node_network_transmit_drop_total{device="eth0"} 0 -node_network_transmit_drop_total{device="flannel.1"} 64 -node_network_transmit_drop_total{device="ibr10:30"} 0 node_network_transmit_drop_total{device="lo"} 0 -node_network_transmit_drop_total{device="lxcbr0"} 0 -node_network_transmit_drop_total{device="tun0"} 0 -node_network_transmit_drop_total{device="veth4B09XN"} 0 -node_network_transmit_drop_total{device="wlan0"} 0 -node_network_transmit_drop_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_transmit_errs_total Network device statistic transmit_errs. # TYPE node_network_transmit_errs_total counter -node_network_transmit_errs_total{device="docker0"} 0 -node_network_transmit_errs_total{device="eth0"} 0 -node_network_transmit_errs_total{device="flannel.1"} 0 -node_network_transmit_errs_total{device="ibr10:30"} 0 node_network_transmit_errs_total{device="lo"} 0 -node_network_transmit_errs_total{device="lxcbr0"} 0 -node_network_transmit_errs_total{device="tun0"} 0 -node_network_transmit_errs_total{device="veth4B09XN"} 0 -node_network_transmit_errs_total{device="wlan0"} 0 -node_network_transmit_errs_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_transmit_fifo_total Network device statistic transmit_fifo. # TYPE node_network_transmit_fifo_total counter -node_network_transmit_fifo_total{device="docker0"} 0 -node_network_transmit_fifo_total{device="eth0"} 0 -node_network_transmit_fifo_total{device="flannel.1"} 0 -node_network_transmit_fifo_total{device="ibr10:30"} 0 node_network_transmit_fifo_total{device="lo"} 0 -node_network_transmit_fifo_total{device="lxcbr0"} 0 -node_network_transmit_fifo_total{device="tun0"} 0 -node_network_transmit_fifo_total{device="veth4B09XN"} 0 -node_network_transmit_fifo_total{device="wlan0"} 0 -node_network_transmit_fifo_total{device="๐Ÿ’ฉ0"} 0 # HELP node_network_transmit_packets_total Network device statistic transmit_packets. # TYPE node_network_transmit_packets_total counter -node_network_transmit_packets_total{device="docker0"} 1.929779e+06 -node_network_transmit_packets_total{device="eth0"} 4.3451486e+07 -node_network_transmit_packets_total{device="flannel.1"} 2.58369223e+08 -node_network_transmit_packets_total{device="ibr10:30"} 0 -node_network_transmit_packets_total{device="lo"} 1.832522e+06 -node_network_transmit_packets_total{device="lxcbr0"} 28339 -node_network_transmit_packets_total{device="tun0"} 934 -node_network_transmit_packets_total{device="veth4B09XN"} 10640 -node_network_transmit_packets_total{device="wlan0"} 1.17262e+07 -node_network_transmit_packets_total{device="๐Ÿ’ฉ0"} 304261 # HELP node_network_transmit_queue_length transmit_queue_length value of /sys/class/net/. # TYPE node_network_transmit_queue_length gauge node_network_transmit_queue_length{device="bond0"} 1000 diff --git a/collector/fixtures/proc/net/dev b/collector/fixtures/proc/net/dev deleted file mode 100644 index a3534c13..00000000 --- a/collector/fixtures/proc/net/dev +++ /dev/null @@ -1,12 +0,0 @@ -Inter-| Receive | Transmit - face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed - tun0: 1888 24 0 0 0 0 0 0 67120 934 0 0 0 0 0 0 -veth4B09XN: 648 8 0 0 0 0 0 0 1943284 10640 0 0 0 0 0 0 - lo: 435303245 1832522 0 0 0 0 0 0 435303245 1832522 0 0 0 0 0 0 - eth0:68210035552 520993275 0 0 0 0 0 0 9315587528 43451486 0 0 0 0 0 0 -lxcbr0: 0 0 0 0 0 0 0 0 2630299 28339 0 0 0 0 0 0 - wlan0: 10437182923 13899359 0 0 0 0 0 0 2851649360 11726200 0 0 0 0 0 0 -docker0: 64910168 1065585 0 0 0 0 0 0 2681662018 1929779 0 0 0 0 0 0 -ibr10:30: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -flannel.1: 18144009813 228499337 0 0 0 0 0 0 20758990068 258369223 0 64 0 0 0 0 - ๐Ÿ’ฉ0: 57750104 105557 0 0 0 0 0 72 404570255 304261 0 0 0 0 0 0 diff --git a/end-to-end-test.sh b/end-to-end-test.sh index 555cd1e1..808c1cdd 100755 --- a/end-to-end-test.sh +++ b/end-to-end-test.sh @@ -65,7 +65,7 @@ cd "$(dirname $0)" port="$((10000 + (RANDOM % 10000)))" tmpdir=$(mktemp -d /tmp/node_exporter_e2e_test.XXXXXX) -skip_re="^(go_|node_exporter_build_info|node_scrape_collector_duration_seconds|process_|node_textfile_mtime_seconds|node_time_(zone|seconds))" +skip_re="^(go_|node_exporter_build_info|node_scrape_collector_duration_seconds|process_|node_textfile_mtime_seconds|node_time_(zone|seconds)|node_network_(receive|transmit)_(bytes|packets)_total)" arch="$(uname -m)" @@ -131,6 +131,7 @@ fi --collector.arp.device-exclude="nope" \ --collector.netclass.ignored-devices="(dmz|int)" \ --collector.netclass.ignore-invalid-speed \ + --collector.netdev.device-include="lo" \ --collector.bcache.priorityStats \ "${cpu_info_collector}" \ --collector.cpu.info.bugs-include="${cpu_info_bugs}" \ From 4851993a63af69b8e1bebbf50038b02b7573ff65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Knecht?= Date: Fri, 9 Jul 2021 09:52:01 +0200 Subject: [PATCH 3/4] collector/netdev_linux_test.go: Add compatibility tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To prepare for the introduction of new metric names, add tests for the legacy metric names and values. This will make it easier to ensure that the code that converts the new metrics to the old ones (for compatibility) behaves correctly. Signed-off-by: Benoรฎt Knecht --- collector/netdev_linux_test.go | 104 ++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/collector/netdev_linux_test.go b/collector/netdev_linux_test.go index 8dae9aa3..541e88d3 100644 --- a/collector/netdev_linux_test.go +++ b/collector/netdev_linux_test.go @@ -127,6 +127,37 @@ var links = []rtnetlink.LinkMessage{ }, }, }, + { + Attributes: &rtnetlink.LinkAttributes{ + Name: "enp0s0f0", + Stats64: &rtnetlink.LinkStats64{ + RXPackets: 226, + TXPackets: 803, + RXBytes: 231424, + TXBytes: 822272, + RXErrors: 14, + TXErrors: 2, + RXDropped: 10, + TXDropped: 17, + Multicast: 285, + Collisions: 30, + RXLengthErrors: 5, + RXOverErrors: 3, + RXCRCErrors: 1, + RXFrameErrors: 4, + RXFIFOErrors: 6, + RXMissedErrors: 21, + TXAbortedErrors: 22, + TXCarrierErrors: 7, + TXFIFOErrors: 24, + TXHeartbeatErrors: 9, + TXWindowErrors: 19, + RXCompressed: 23, + TXCompressed: 20, + RXNoHandler: 62, + }, + }, + }, } func TestNetDevStatsIgnore(t *testing.T) { @@ -146,7 +177,7 @@ func TestNetDevStatsIgnore(t *testing.T) { t.Errorf("want netstat tun0 packets %v, got %v", want, got) } - if want, got := 9, len(netStats); want != got { + if want, got := 10, len(netStats); want != got { t.Errorf("want count of devices to be %d, got %d", want, got) } @@ -174,3 +205,74 @@ func TestNetDevStatsAccept(t *testing.T) { t.Error("want fixture interface ๐Ÿ’ฉ0 to exist, but it does not") } } + +func TestNetDevLegacyMetricNames(t *testing.T) { + expected := []string{ + "receive_packets", + "transmit_packets", + "receive_bytes", + "transmit_bytes", + "receive_errs", + "transmit_errs", + "receive_drop", + "transmit_drop", + "receive_multicast", + "transmit_colls", + "receive_frame", + "receive_fifo", + "transmit_carrier", + "transmit_fifo", + "receive_compressed", + "transmit_compressed", + } + + filter := newDeviceFilter("", "") + netStats := netlinkStats(links, &filter, log.NewNopLogger()) + + for dev, devStats := range netStats { + for _, name := range expected { + if _, ok := devStats[name]; !ok { + t.Errorf("metric %s should be defined on interface %s", name, dev) + } + } + } +} + +func TestNetDevLegacyMetricValues(t *testing.T) { + expected := map[string]uint64{ + "receive_packets": 226, + "transmit_packets": 803, + "receive_bytes": 231424, + "transmit_bytes": 822272, + "receive_errs": 14, + "transmit_errs": 2, + "receive_drop": 10 + 21, + "transmit_drop": 17, + "receive_multicast": 285, + "transmit_colls": 30, + "receive_frame": 5 + 3 + 1 + 4, + "receive_fifo": 6, + "transmit_carrier": 22 + 7 + 9 + 19, + "transmit_fifo": 24, + "receive_compressed": 23, + "transmit_compressed": 20, + } + + filter := newDeviceFilter("", "^enp0s0f0$") + netStats := netlinkStats(links, &filter, log.NewNopLogger()) + metrics, ok := netStats["enp0s0f0"] + if !ok { + t.Error("expected stats for interface enp0s0f0") + } + + for name, want := range expected { + got, ok := metrics[name] + if !ok { + t.Errorf("metric %s should be defined on interface enp0s0f0", name) + continue + } + if want != got { + t.Errorf("want %s %d, got %d", name, want, got) + } + } +} From b25273fac00c7318c970a7330b1204d2630e6f58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Knecht?= Date: Fri, 9 Jul 2021 11:44:03 +0200 Subject: [PATCH 4/4] collector/netdev_*: Add detailed interface stats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Linux, we get more detailed interface statistics from netlink than we did from `/proc/net/dev`. This commit adds a new flag (`--collector.netdev.enable-detailed-metrics`) to expose those statistics under new (incompatible) metric names. When enabled, the metric names are also changed on Darwin and BSD platforms to keep everything consistent, but it doesn't provide more detailed statistics on those platforms. The old metrics can be derived from the new ones using the following rules ([dev_seq_printf_stats]): - `receive_errs` = `receive_errors` - `receive_drop` = `receive_dropped` + `receive_missed_errors` - `receive_fifo` = `receive_fifo_errors` - `receive_frame` = `receive_length_errors` + `receive_over_errors` + `receive_crc_errors` + `receive_frame_errors` - `receive_multicast` = `multicast` - `transmit_errs` = `transmit_errors` - `transmit_drop` = `transmit_dropped` - `transmit_fifo` = `transmit_fifo_errors` - `transmit_colls` = `collisions` - `transmit_carrier` = `transmit_aborted_errors` + `transmit_carrier_errors` + `transmit_heartbeat_errors` + `transmit_window_errors` [dev_seq_printf_stats]: https://github.com/torvalds/linux/blob/master/net/core/net-procfs.c#L75-L97 Signed-off-by: Benoรฎt Knecht --- collector/netdev_bsd.go | 8 ++-- collector/netdev_common.go | 55 ++++++++++++++++++++++++++ collector/netdev_darwin.go | 8 +++- collector/netdev_linux.go | 43 +++++++++++++-------- collector/netdev_linux_test.go | 64 ++++++++++++++++++++++++++++++- collector/netdev_openbsd.go | 10 +++-- collector/netdev_openbsd_amd64.go | 10 +++-- 7 files changed, 169 insertions(+), 29 deletions(-) diff --git a/collector/netdev_bsd.go b/collector/netdev_bsd.go index dc4d1a4f..691bbec4 100644 --- a/collector/netdev_bsd.go +++ b/collector/netdev_bsd.go @@ -59,14 +59,14 @@ func getNetDevStats(filter *deviceFilter, logger log.Logger) (netDevStats, error 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_errors": uint64(data.ifi_ierrors), + "transmit_errors": uint64(data.ifi_oerrors), + "receive_dropped": uint64(data.ifi_iqdrops), + "transmit_dropped": uint64(data.ifi_oqdrops), "receive_multicast": uint64(data.ifi_imcasts), "transmit_multicast": uint64(data.ifi_omcasts), - "receive_drop": uint64(data.ifi_iqdrops), - "transmit_drop": uint64(data.ifi_oqdrops), } } diff --git a/collector/netdev_common.go b/collector/netdev_common.go index 19b07f8c..0a9b522b 100644 --- a/collector/netdev_common.go +++ b/collector/netdev_common.go @@ -36,6 +36,7 @@ var ( netdevDeviceExclude = kingpin.Flag("collector.netdev.device-exclude", "Regexp of net devices to exclude (mutually exclusive to device-include).").String() oldNetdevDeviceExclude = kingpin.Flag("collector.netdev.device-blacklist", "DEPRECATED: Use collector.netdev.device-exclude").Hidden().String() netdevAddressInfo = kingpin.Flag("collector.netdev.address-info", "Collect address-info for every device").Bool() + netdevDetailedMetrics = kingpin.Flag("collector.netdev.enable-detailed-metrics", "Use (incompatible) metric names that provide more detailed stats on Linux").Bool() ) type netDevCollector struct { @@ -114,6 +115,9 @@ func (c *netDevCollector) Update(ch chan<- prometheus.Metric) error { return fmt.Errorf("couldn't get netstats: %w", err) } for dev, devStats := range netDev { + if !*netdevDetailedMetrics { + legacy(devStats) + } for key, value := range devStats { desc := c.metricDesc(key) ch <- prometheus.MustNewConstMetric(desc, prometheus.CounterValue, float64(value), dev) @@ -184,3 +188,54 @@ func getAddrsInfo(interfaces []net.Interface) []addrInfo { return res } + +// https://github.com/torvalds/linux/blob/master/net/core/net-procfs.c#L75-L97 +func legacy(metrics map[string]uint64) { + if metric, ok := pop(metrics, "receive_errors"); ok { + metrics["receive_errs"] = metric + } + if metric, ok := pop(metrics, "receive_dropped"); ok { + metrics["receive_drop"] = metric + popz(metrics, "receive_missed_errors") + } + if metric, ok := pop(metrics, "receive_fifo_errors"); ok { + metrics["receive_fifo"] = metric + } + if metric, ok := pop(metrics, "receive_frame_errors"); ok { + metrics["receive_frame"] = metric + popz(metrics, "receive_length_errors") + popz(metrics, "receive_over_errors") + popz(metrics, "receive_crc_errors") + } + if metric, ok := pop(metrics, "multicast"); ok { + metrics["receive_multicast"] = metric + } + if metric, ok := pop(metrics, "transmit_errors"); ok { + metrics["transmit_errs"] = metric + } + if metric, ok := pop(metrics, "transmit_dropped"); ok { + metrics["transmit_drop"] = metric + } + if metric, ok := pop(metrics, "transmit_fifo_errors"); ok { + metrics["transmit_fifo"] = metric + } + if metric, ok := pop(metrics, "multicast"); ok { + metrics["receive_multicast"] = metric + } + if metric, ok := pop(metrics, "collisions"); ok { + metrics["transmit_colls"] = metric + } + if metric, ok := pop(metrics, "transmit_carrier_errors"); ok { + metrics["transmit_carrier"] = metric + popz(metrics, "transmit_aborted_errors") + popz(metrics, "transmit_heartbeat_errors") + popz(metrics, "transmit_window_errors") + } +} + +func pop(m map[string]uint64, key string) (uint64, bool) { + value, ok := m[key] + delete(m, key) + return value, ok +} + +func popz(m map[string]uint64, key string) uint64 { + if value, ok := m[key]; ok { + delete(m, key) + return value + } + return 0 +} diff --git a/collector/netdev_darwin.go b/collector/netdev_darwin.go index 2ce3d9df..c08f1f8e 100644 --- a/collector/netdev_darwin.go +++ b/collector/netdev_darwin.go @@ -50,12 +50,15 @@ func getNetDevStats(filter *deviceFilter, logger log.Logger) (netDevStats, error 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_errors": ifaceData.Data.Ierrors, + "transmit_errors": ifaceData.Data.Oerrors, + "receive_dropped": ifaceData.Data.Iqdrops, "receive_multicast": ifaceData.Data.Imcasts, "transmit_multicast": ifaceData.Data.Omcasts, + "collisions": ifaceData.Data.Collisions, + "noproto": ifaceData.Data.Noproto, } } @@ -87,6 +90,7 @@ type ifMsghdr2 struct { Data ifData64 } +// https://github.com/apple/darwin-xnu/blob/main/bsd/net/if_var.h#L199-L231 type ifData64 struct { Type uint8 Typelen uint8 diff --git a/collector/netdev_linux.go b/collector/netdev_linux.go index 5a0d5c34..325d10b7 100644 --- a/collector/netdev_linux.go +++ b/collector/netdev_linux.go @@ -51,24 +51,37 @@ func netlinkStats(links []rtnetlink.LinkMessage, filter *deviceFilter, logger lo } // https://github.com/torvalds/linux/blob/master/include/uapi/linux/if_link.h#L42-L246 - // https://github.com/torvalds/linux/blob/master/net/core/net-procfs.c#L75-L97 metrics[name] = map[string]uint64{ - "receive_packets": stats.RXPackets, - "transmit_packets": stats.TXPackets, - "receive_bytes": stats.RXBytes, - "transmit_bytes": stats.TXBytes, - "receive_errs": stats.RXErrors, - "transmit_errs": stats.TXErrors, - "receive_drop": stats.RXDropped + stats.RXMissedErrors, - "transmit_drop": stats.TXDropped, - "receive_multicast": stats.Multicast, - "transmit_colls": stats.Collisions, - "receive_frame": stats.RXLengthErrors + stats.RXOverErrors + stats.RXCRCErrors + stats.RXFrameErrors, - "receive_fifo": stats.RXFIFOErrors, - "transmit_carrier": stats.TXAbortedErrors + stats.TXCarrierErrors + stats.TXHeartbeatErrors + stats.TXWindowErrors, - "transmit_fifo": stats.TXFIFOErrors, + "receive_packets": stats.RXPackets, + "transmit_packets": stats.TXPackets, + "receive_bytes": stats.RXBytes, + "transmit_bytes": stats.TXBytes, + "receive_errors": stats.RXErrors, + "transmit_errors": stats.TXErrors, + "receive_dropped": stats.RXDropped, + "transmit_dropped": stats.TXDropped, + "multicast": stats.Multicast, + "collisions": stats.Collisions, + + // detailed rx_errors + "receive_length_errors": stats.RXLengthErrors, + "receive_over_errors": stats.RXOverErrors, + "receive_crc_errors": stats.RXCRCErrors, + "receive_frame_errors": stats.RXFrameErrors, + "receive_fifo_errors": stats.RXFIFOErrors, + "receive_missed_errors": stats.RXMissedErrors, + + // detailed tx_errors + "transmit_aborted_errors": stats.TXAbortedErrors, + "transmit_carrier_errors": stats.TXCarrierErrors, + "transmit_fifo_errors": stats.TXFIFOErrors, + "transmit_heartbeat_errors": stats.TXHeartbeatErrors, + "transmit_window_errors": stats.TXWindowErrors, + + // for cslip etc "receive_compressed": stats.RXCompressed, "transmit_compressed": stats.TXCompressed, + "receive_nohandler": stats.RXNoHandler, } } diff --git a/collector/netdev_linux_test.go b/collector/netdev_linux_test.go index 541e88d3..32e3d16b 100644 --- a/collector/netdev_linux_test.go +++ b/collector/netdev_linux_test.go @@ -189,7 +189,7 @@ func TestNetDevStatsIgnore(t *testing.T) { t.Error("want fixture interface ibr10:30 to exist, but it does not") } - if want, got := uint64(72), netStats["๐Ÿ’ฉ0"]["receive_multicast"]; want != got { + if want, got := uint64(72), netStats["๐Ÿ’ฉ0"]["multicast"]; want != got { t.Error("want fixture interface ๐Ÿ’ฉ0 to exist, but it does not") } } @@ -201,7 +201,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 := uint64(72), netStats["๐Ÿ’ฉ0"]["receive_multicast"]; want != got { + if want, got := uint64(72), netStats["๐Ÿ’ฉ0"]["multicast"]; want != got { t.Error("want fixture interface ๐Ÿ’ฉ0 to exist, but it does not") } } @@ -230,6 +230,7 @@ func TestNetDevLegacyMetricNames(t *testing.T) { netStats := netlinkStats(links, &filter, log.NewNopLogger()) for dev, devStats := range netStats { + legacy(devStats) for _, name := range expected { if _, ok := devStats[name]; !ok { t.Errorf("metric %s should be defined on interface %s", name, dev) @@ -265,6 +266,8 @@ func TestNetDevLegacyMetricValues(t *testing.T) { t.Error("expected stats for interface enp0s0f0") } + legacy(metrics) + for name, want := range expected { got, ok := metrics[name] if !ok { @@ -276,3 +279,60 @@ func TestNetDevLegacyMetricValues(t *testing.T) { } } } + +func TestNetDevMetricValues(t *testing.T) { + filter := newDeviceFilter("", "") + netStats := netlinkStats(links, &filter, log.NewNopLogger()) + + for _, msg := range links { + device := msg.Attributes.Name + stats := msg.Attributes.Stats64 + + expected := map[string]uint64{ + "receive_packets": stats.RXPackets, + "transmit_packets": stats.TXPackets, + "receive_bytes": stats.RXBytes, + "transmit_bytes": stats.TXBytes, + "receive_errors": stats.RXErrors, + "transmit_errors": stats.TXErrors, + "receive_dropped": stats.RXDropped, + "transmit_dropped": stats.TXDropped, + "multicast": stats.Multicast, + "collisions": stats.Collisions, + + // detailed rx_errors + "receive_length_errors": stats.RXLengthErrors, + "receive_over_errors": stats.RXOverErrors, + "receive_crc_errors": stats.RXCRCErrors, + "receive_frame_errors": stats.RXFrameErrors, + "receive_fifo_errors": stats.RXFIFOErrors, + "receive_missed_errors": stats.RXMissedErrors, + + // detailed tx_errors + "transmit_aborted_errors": stats.TXAbortedErrors, + "transmit_carrier_errors": stats.TXCarrierErrors, + "transmit_fifo_errors": stats.TXFIFOErrors, + "transmit_heartbeat_errors": stats.TXHeartbeatErrors, + "transmit_window_errors": stats.TXWindowErrors, + + // for cslip etc + "receive_compressed": stats.RXCompressed, + "transmit_compressed": stats.TXCompressed, + "receive_nohandler": stats.RXNoHandler, + } + + for name, want := range expected { + devStats, ok := netStats[device] + if !ok { + t.Errorf("expected stats for interface %s", device) + } + got, ok := devStats[name] + if !ok { + t.Errorf("metric %s should be defined on interface %s", name, device) + } + if want != got { + t.Errorf("want %s %d, got %d", name, want, got) + } + } + } +} diff --git a/collector/netdev_openbsd.go b/collector/netdev_openbsd.go index 639b9ec1..5d53678d 100644 --- a/collector/netdev_openbsd.go +++ b/collector/netdev_openbsd.go @@ -53,16 +53,20 @@ func getNetDevStats(filter *deviceFilter, logger log.Logger) (netDevStats, error data := (*C.struct_if_data)(ifa.ifa_data) + // https://github.com/openbsd/src/blob/master/sys/net/if.h#L101-L126 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_errors": uint64(data.ifi_ierrors), + "transmit_errors": uint64(data.ifi_oerrors), + "receive_dropped": uint64(data.ifi_iqdrops), + "transmit_dropped": uint64(data.ifi_oqdrops), "receive_multicast": uint64(data.ifi_imcasts), "transmit_multicast": uint64(data.ifi_omcasts), - "receive_drop": uint64(data.ifi_iqdrops), + "collisions": uint64(data.ifi_collisions), + "noproto": uint64(data.ifi_noproto), } } diff --git a/collector/netdev_openbsd_amd64.go b/collector/netdev_openbsd_amd64.go index 07f458e4..da8a81f3 100644 --- a/collector/netdev_openbsd_amd64.go +++ b/collector/netdev_openbsd_amd64.go @@ -58,16 +58,20 @@ func getNetDevStats(filter *deviceFilter, logger log.Logger) (netDevStats, error continue } + // https://cs.opensource.google/go/x/sys/+/master:unix/ztypes_openbsd_amd64.go;l=292-316 netDev[dev] = map[string]uint64{ "receive_packets": data.Ipackets, "transmit_packets": data.Opackets, - "receive_errs": data.Ierrors, - "transmit_errs": data.Oerrors, "receive_bytes": data.Ibytes, "transmit_bytes": data.Obytes, + "receive_errors": data.Ierrors, + "transmit_errors": data.Oerrors, + "receive_dropped": data.Iqdrops, + "transmit_dropped": data.Oqdrops, "receive_multicast": data.Imcasts, "transmit_multicast": data.Omcasts, - "receive_drop": data.Iqdrops, + "collisions": data.Collisions, + "noproto": data.Noproto, } } return netDev, nil