blob: 1a4919def4b10b46cbd5aad3c7080b00177471b0 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2017 The ChromiumOS Authors
Allen Li325c0762017-03-02 15:00:19 -08002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Network metrics."""
6
Allen Li13bdf0c2017-03-02 15:18:16 -08007from __future__ import absolute_import
Allen Li13bdf0c2017-03-02 15:18:16 -08008
Allen Lieb107022017-05-04 13:19:17 -07009import collections
Chris McDonald59650c32021-07-20 15:29:28 -060010import logging
Allen Lib6bb5f82017-08-21 15:11:57 -070011import socket
Allen Lieb107022017-05-04 13:19:17 -070012
Chris McDonald59650c32021-07-20 15:29:28 -060013from chromite.third_party.infra_libs import ts_mon
Mike Frysingercb56b642019-08-25 15:33:08 -040014import psutil # pylint: disable=import-error
Allen Li325c0762017-03-02 15:00:19 -080015
Allen Lia9c6e802017-07-11 15:42:47 -070016from chromite.lib import metrics
Mike Frysinger8d6a51d2021-02-12 07:40:03 -050017
Allen Li325c0762017-03-02 15:00:19 -080018
19logger = logging.getLogger(__name__)
20
21_BOOT_TIME = psutil.boot_time()
22
Allen Lia9c6e802017-07-11 15:42:47 -070023_net_bytes_metric = metrics.CounterMetric(
Alex Klein1699fab2022-09-08 08:46:06 -060024 "dev/net/bytes",
25 start_time=_BOOT_TIME,
26 description="Number of bytes up/down on interface.",
27)
Allen Lia9c6e802017-07-11 15:42:47 -070028_net_packets_metric = metrics.CounterMetric(
Alex Klein1699fab2022-09-08 08:46:06 -060029 "dev/net/packets",
30 start_time=_BOOT_TIME,
31 description="Number of packets up/down on interface.",
32)
Allen Lia9c6e802017-07-11 15:42:47 -070033_net_errors_metric = metrics.CounterMetric(
Alex Klein1699fab2022-09-08 08:46:06 -060034 "dev/net/errors",
35 start_time=_BOOT_TIME,
36 description="Total number of errors up/down on interface.",
37)
Allen Lia9c6e802017-07-11 15:42:47 -070038_net_dropped_metric = metrics.CounterMetric(
Alex Klein1699fab2022-09-08 08:46:06 -060039 "dev/net/dropped",
40 start_time=_BOOT_TIME,
41 description="Total number of dropped packages up/down on interface.",
42)
Allen Lieb107022017-05-04 13:19:17 -070043
Allen Lia9c6e802017-07-11 15:42:47 -070044_net_if_isup_metric = metrics.BooleanMetric(
Alex Klein1699fab2022-09-08 08:46:06 -060045 "dev/net/isup", description="Whether interface is up or down."
46)
Allen Lia9c6e802017-07-11 15:42:47 -070047_net_if_duplex_metric = metrics.GaugeMetric(
Alex Klein1699fab2022-09-08 08:46:06 -060048 "dev/net/duplex",
49 description="Whether interface supports full or half duplex.",
50)
Allen Lia9c6e802017-07-11 15:42:47 -070051_net_if_speed_metric = metrics.GaugeMetric(
Alex Klein1699fab2022-09-08 08:46:06 -060052 "dev/net/speed", description="Network interface speed in Mb."
53)
Allen Lia9c6e802017-07-11 15:42:47 -070054_net_if_mtu_metric = metrics.GaugeMetric(
Alex Klein1699fab2022-09-08 08:46:06 -060055 "dev/net/mtu", description="Network interface MTU in B."
56)
Allen Li325c0762017-03-02 15:00:19 -080057
58
59def collect_net_info():
Alex Klein1699fab2022-09-08 08:46:06 -060060 """Collect network metrics."""
61 _collect_net_io_duplex_counters()
62 _collect_net_if_stats()
63 _collect_fqdn()
64 _collect_net_if_addrs()
Allen Li325c0762017-03-02 15:00:19 -080065
66
Allen Lieb107022017-05-04 13:19:17 -070067# Network IO metrics to collect
Alex Klein1699fab2022-09-08 08:46:06 -060068_IOMetric = collections.namedtuple(
69 "_IOMetric", ["metric", "up_counter_name", "down_counter_name"]
70)
Allen Lieb107022017-05-04 13:19:17 -070071
72_net_io_duplex_metrics = (
Alex Klein1699fab2022-09-08 08:46:06 -060073 _IOMetric(
74 metric=_net_bytes_metric,
75 up_counter_name="bytes_sent",
76 down_counter_name="bytes_recv",
77 ),
78 _IOMetric(
79 metric=_net_packets_metric,
80 up_counter_name="packets_sent",
81 down_counter_name="packets_recv",
82 ),
83 _IOMetric(
84 metric=_net_errors_metric,
85 up_counter_name="errout",
86 down_counter_name="errin",
87 ),
88 _IOMetric(
89 metric=_net_dropped_metric,
90 up_counter_name="dropout",
91 down_counter_name="dropin",
92 ),
Allen Lieb107022017-05-04 13:19:17 -070093)
94
95
96def _collect_net_io_duplex_counters():
Alex Klein1699fab2022-09-08 08:46:06 -060097 """Collect metrics for network IO duplex counters."""
98 for nic, counters in _net_io_iter():
99 fields = {"interface": nic}
100 for (
101 metric,
102 up_counter_name,
103 down_counter_name,
104 ) in _net_io_duplex_metrics:
105 try:
106 metric.set(
107 getattr(counters, up_counter_name),
108 fields=dict(direction="up", **fields),
109 )
110 metric.set(
111 getattr(counters, down_counter_name),
112 fields=dict(direction="down", **fields),
113 )
114 except ts_mon.MonitoringDecreasingValueError as ex:
115 # This normally shouldn't happen, but might if the network
116 # driver module is reloaded, so log an error and continue
117 # instead of raising an exception.
118 logger.warning(str(ex))
Allen Lieb107022017-05-04 13:19:17 -0700119
120
Allen Li4bb931f2017-05-04 13:11:56 -0700121def _net_io_iter():
Alex Klein1699fab2022-09-08 08:46:06 -0600122 """Generate network IO information."""
123 nics = psutil.net_io_counters(pernic=True)
124 for nic, counters in nics.items():
125 if _is_virtual_netif(nic):
126 continue
127 yield nic, counters
Allen Li4bb931f2017-05-04 13:11:56 -0700128
129
Allen Li325c0762017-03-02 15:00:19 -0800130_net_if_metrics = (
Alex Klein1699fab2022-09-08 08:46:06 -0600131 (_net_if_isup_metric, "isup"),
132 (_net_if_duplex_metric, "duplex"),
133 (_net_if_speed_metric, "speed"),
134 (_net_if_mtu_metric, "mtu"),
Allen Li325c0762017-03-02 15:00:19 -0800135)
136
137
138def _collect_net_if_stats():
Alex Klein1699fab2022-09-08 08:46:06 -0600139 """Collect metrics for network interface stats."""
140 for nic, stats in psutil.net_if_stats().items():
141 if _is_virtual_netif(nic):
142 continue
143 fields = {"interface": nic}
144 for metric, counter_name in _net_if_metrics:
145 metric.set(getattr(stats, counter_name), fields=fields)
Allen Li325c0762017-03-02 15:00:19 -0800146
147
Prathmesh Prabhu07f80872017-08-21 15:09:33 -0700148_net_if_addrs_metrics = metrics.StringMetric(
Alex Klein1699fab2022-09-08 08:46:06 -0600149 "dev/net/address",
150 description="Network address of physical network interfaces.",
151)
Prathmesh Prabhu07f80872017-08-21 15:09:33 -0700152_family_field_strings = {
Alex Klein1699fab2022-09-08 08:46:06 -0600153 psutil.AF_LINK: "AF_LINK",
154 socket.AF_INET: "AF_INET",
155 socket.AF_INET6: "AF_INET6",
Prathmesh Prabhu07f80872017-08-21 15:09:33 -0700156}
157
158
159def _collect_net_if_addrs():
Alex Klein1699fab2022-09-08 08:46:06 -0600160 """Collects network addresses as metrics."""
161 for nic, addresses in psutil.net_if_addrs().items():
162 if _is_virtual_netif(nic):
163 continue
164 for address in addresses:
165 fields = {
166 "interface": nic,
167 "family": _family_field_strings.get(address.family, "UNKNOWN"),
168 }
169 _net_if_addrs_metrics.set(address.address, fields)
Prathmesh Prabhu07f80872017-08-21 15:09:33 -0700170
171
Allen Li325c0762017-03-02 15:00:19 -0800172def _is_virtual_netif(nic):
Alex Klein1699fab2022-09-08 08:46:06 -0600173 """Return whether the network interface is virtual."""
174 # TODO(ayatane): Use a different way of identifying virtual interfaces
175 return nic.startswith("veth")
Allen Lib6bb5f82017-08-21 15:11:57 -0700176
177
Alex Klein1699fab2022-09-08 08:46:06 -0600178_fqdn_metric = metrics.StringMetric("net/fqdn", description="FQDN")
Allen Lib6bb5f82017-08-21 15:11:57 -0700179
180
181def _collect_fqdn():
Alex Klein1699fab2022-09-08 08:46:06 -0600182 fqdn = socket.getfqdn()
183 logging.debug("Got FQDN: %s", fqdn)
184 _fqdn_metric.set(fqdn)