blob: 394ac52e935b5382971d69865c745d11eb4aec7f [file] [log] [blame]
Allen Li325c0762017-03-02 15:00:19 -08001# Copyright 2017 The Chromium OS Authors. All rights reserved.
2# 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
8from __future__ import print_function
Allen Li13bdf0c2017-03-02 15:18:16 -08009
Allen Lieb107022017-05-04 13:19:17 -070010import collections
11
Allen Li325c0762017-03-02 15:00:19 -080012import psutil
13
14from chromite.lib import cros_logging as logging
Allen Lia9c6e802017-07-11 15:42:47 -070015from chromite.lib import metrics
Allen Li325c0762017-03-02 15:00:19 -080016
17logger = logging.getLogger(__name__)
18
19_BOOT_TIME = psutil.boot_time()
20
Allen Lia9c6e802017-07-11 15:42:47 -070021_net_bytes_metric = metrics.CounterMetric(
Allen Lieb107022017-05-04 13:19:17 -070022 'dev/net/bytes', start_time=_BOOT_TIME,
Allen Li22989bd2017-07-12 10:34:37 -070023 description='Number of bytes up/down on interface.')
Allen Lia9c6e802017-07-11 15:42:47 -070024_net_packets_metric = metrics.CounterMetric(
Allen Lieb107022017-05-04 13:19:17 -070025 'dev/net/packets', start_time=_BOOT_TIME,
Allen Li22989bd2017-07-12 10:34:37 -070026 description='Number of packets up/down on interface.')
Allen Lia9c6e802017-07-11 15:42:47 -070027_net_errors_metric = metrics.CounterMetric(
Allen Lieb107022017-05-04 13:19:17 -070028 'dev/net/errors', start_time=_BOOT_TIME,
29 description='Total number of errors up/down on interface.')
Allen Lia9c6e802017-07-11 15:42:47 -070030_net_dropped_metric = metrics.CounterMetric(
Allen Lieb107022017-05-04 13:19:17 -070031 'dev/net/dropped', start_time=_BOOT_TIME,
32 description='Total number of dropped packages up/down on interface.')
33
Allen Lia9c6e802017-07-11 15:42:47 -070034_net_if_isup_metric = metrics.BooleanMetric(
Allen Li325c0762017-03-02 15:00:19 -080035 'dev/net/isup',
36 description='Whether interface is up or down.')
Allen Lia9c6e802017-07-11 15:42:47 -070037_net_if_duplex_metric = metrics.GaugeMetric(
Allen Li325c0762017-03-02 15:00:19 -080038 'dev/net/duplex',
39 description='Whether interface supports full or half duplex.')
Allen Lia9c6e802017-07-11 15:42:47 -070040_net_if_speed_metric = metrics.GaugeMetric(
Allen Li325c0762017-03-02 15:00:19 -080041 'dev/net/speed',
42 description='Network interface speed in Mb.')
Allen Lia9c6e802017-07-11 15:42:47 -070043_net_if_mtu_metric = metrics.GaugeMetric(
Allen Li325c0762017-03-02 15:00:19 -080044 'dev/net/mtu',
45 description='Network interface MTU in B.')
46
47
48def collect_net_info():
49 """Collect network metrics."""
Allen Lieb107022017-05-04 13:19:17 -070050 _collect_net_io_duplex_counters()
Allen Li325c0762017-03-02 15:00:19 -080051 _collect_net_if_stats()
52
53
Allen Lieb107022017-05-04 13:19:17 -070054# Network IO metrics to collect
55_IOMetric = collections.namedtuple('_IOMetric', ['metric', 'up_counter_name',
56 'down_counter_name'])
57
58_net_io_duplex_metrics = (
Allen Li22989bd2017-07-12 10:34:37 -070059 _IOMetric(metric=_net_bytes_metric,
60 up_counter_name='bytes_sent',
61 down_counter_name='bytes_recv'),
62 _IOMetric(metric=_net_packets_metric,
63 up_counter_name='packets_sent',
64 down_counter_name='packets_recv'),
65 _IOMetric(metric=_net_errors_metric,
66 up_counter_name='errout',
67 down_counter_name='errin'),
68 _IOMetric(metric=_net_dropped_metric,
69 up_counter_name='dropout',
70 down_counter_name='dropin'),
Allen Lieb107022017-05-04 13:19:17 -070071)
72
73
74def _collect_net_io_duplex_counters():
75 """Collect metrics for network IO duplex counters."""
76 for nic, counters in _net_io_iter():
77 fields = {'interface': nic}
78 for metric, up_counter_name, down_counter_name in _net_io_duplex_metrics:
79 try:
80 metric.set(getattr(counters, up_counter_name),
81 fields=dict(direction='up', **fields))
82 metric.set(getattr(counters, down_counter_name),
83 fields=dict(direction='down', **fields))
Allen Lia9c6e802017-07-11 15:42:47 -070084 except metrics.MonitoringDecreasingValueError as ex:
Allen Lieb107022017-05-04 13:19:17 -070085 # This normally shouldn't happen, but might if the network
86 # driver module is reloaded, so log an error and continue
87 # instead of raising an exception.
88 logger.warning(str(ex))
89
90
Allen Li4bb931f2017-05-04 13:11:56 -070091def _net_io_iter():
92 """Generate network IO information."""
93 nics = psutil.net_io_counters(pernic=True)
94 for nic, counters in nics.iteritems():
95 if _is_virtual_netif(nic):
96 continue
97 yield nic, counters
98
99
Allen Li325c0762017-03-02 15:00:19 -0800100_net_if_metrics = (
Allen Li22989bd2017-07-12 10:34:37 -0700101 (_net_if_isup_metric, 'isup'),
102 (_net_if_duplex_metric, 'duplex'),
103 (_net_if_speed_metric, 'speed'),
104 (_net_if_mtu_metric, 'mtu'),
Allen Li325c0762017-03-02 15:00:19 -0800105)
106
107
108def _collect_net_if_stats():
109 """Collect metrics for network interface stats."""
110 for nic, stats in psutil.net_if_stats().iteritems():
111 if _is_virtual_netif(nic):
112 continue
113 fields = {'interface': nic}
114 for metric, counter_name in _net_if_metrics:
115 metric.set(getattr(stats, counter_name), fields=fields)
116
117
118def _is_virtual_netif(nic):
Allen Li22989bd2017-07-12 10:34:37 -0700119 """Return whether the network interface is virtual."""
120 # TODO(ayatane): Use a different way of identifying virtual interfaces
121 return nic.startswith('veth')