diff --git a/collectors/available/linux/long-lived/ifstat.py b/collectors/available/linux/long-lived/ifstat.py index 6a19865c..ef1cec0d 100755 --- a/collectors/available/linux/long-lived/ifstat.py +++ b/collectors/available/linux/long-lived/ifstat.py @@ -22,8 +22,7 @@ COLLECTION_INTERVAL = 15 # seconds -# /proc/net/dev has 16 fields, 8 for receive and 8 for transmit, -# defined below. +# /proc/net/dev has 16 fields, 8 for receive and 8 for transmit, defined below. # So we can aggregate up the total bytes, packets, etc # we tag each metric with direction=in or =out # and iface= @@ -35,58 +34,56 @@ # PCI add-in interfaces # pp_ +FIELDS = ("bytes", "packets", "errs", "drop", "fifo", "frame", "compressed", "multicast", # receive + "bytes", "packets", "errs", "drop", "fifo", "colls", "carrier", "compressed") # transmit -FIELDS = ("bytes", "packets", "errs", "dropped", - "fifo.errs", "frame.errs", "compressed", "multicast", - "bytes", "packets", "errs", "dropped", - "fifo.errs", "collisions", "carrier.errs", "compressed") +PATTERN = re.compile(r''' + \s* # Leading whitespace + (?P\w+):\s+ # Network interface name followed by colon and whitespace + + (?P\d+)\s+ # Receive bytes + (?P\d+)\s+ # Receive packets + (?P\d+)\s+ # Receive errors + (?P\d+)\s+ # Receive dropped packets + (?P\d+)\s+ # Receive FIFO errors + (?P\d+)\s+ # Receive frame errors + (?P\d+)\s+ # Receive compressed packets + (?P\d+)\s+ # Receive multicast packets + (?P\d+)\s+ # Transmit bytes + (?P\d+)\s+ # Transmit packets + (?P\d+)\s+ # Transmit errors + (?P\d+)\s+ # Transmit dropped packets + (?P\d+)\s+ # Transmit FIFO errors + (?P\d+)\s+ # Transmit collisions + (?P\d+)\s+ # Transmit carrier errors + (?P\d+)\s* # Transmit compressed packets + ''', re.VERBOSE) def main(): """ifstat main loop""" - f_netdev = open("/proc/net/dev") + f_netdev = open("/proc/net/dev", encoding='utf-8') utils.drop_privileges() - # We just care about ethN and emN interfaces. We specifically - # want to avoid bond interfaces, because interface - # stats are still kept on the child interfaces when - # you bond. By skipping bond we avoid double counting. + # We just care about ethN and emN interfaces. We specifically want to avoid + # bond interfaces, because interface stats are still kept on the child interfaces + # when you bond. By skipping bond we avoid double counting. while True: f_netdev.seek(0) - ts = int(time.time()) + time_stamp = int(time.time()) for line in f_netdev: - m = re.match(r''' - \s* - ( - eth?\d+ | - em\d+_\d+/\d+ | em\d+_\d+ | em\d+ | - p\d+p\d+_\d+/\d+ | p\d+p\d+_\d+ | p\d+p\d+ | - (?: # Start of 'predictable network interface names' - (?:en|sl|wl|ww) - (?: - b\d+ | # BCMA bus - c[0-9a-f]+ | # CCW bus group - o\d+(?:d\d+)? | # On-board device - s\d+(?:f\d+)?(?:d\d+)? | # Hotplug slots - x[0-9a-f]+ | # Raw MAC address - p\d+s\d+(?:f\d+)?(?:d\d+)? | # PCI geographic loc - p\d+s\d+(?:f\d+)?(?:u\d+)*(?:c\d+)?(?:i\d+)? # USB - ) - ) - ):(.*)''', line, re.VERBOSE) - if not m: + match = PATTERN.match(line) + + if not match: + continue + + if match.group('interface').startswith('bond'): # avoid bond interface continue - intf = m.group(1) - stats = m.group(2).split(None) - def direction(i): - if i >= 8: - return "out" - return "in" for i in range(16): - print("proc.net.%s %d %s iface=%s direction=%s" - % (FIELDS[i], ts, stats[i], intf, direction(i))) + print(f"proc.net.{FIELDS[i]} {time_stamp} {match.group(i+2)} " + f"iface={match.group('interface')} direction={'in' if i < 8 else 'out'}") sys.stdout.flush() time.sleep(COLLECTION_INTERVAL)