compare records to previous record within 1s time frame
[bwmon.git] / bwmon / aggregator.py
blobd179821bde1e2fdfcc08c30fb87a0116dcddb36f
1 from subprocess import Popen, PIPE
2 from datetime import datetime
3 import re
4 import collections
5 import shlex
7 class Aggregator():
9 def __init__(self, monitors):
10 self.monitors = monitors
11 self.line_regex = re.compile('\s*(?P<in>\d+)\s*/\s*(?P<out>\d+)\s*--\s*(?P<proc>.*)')
13 def launch_monitors(self):
15 outpipe = PIPE
17 for m in self.monitors:
18 args = shlex.split(m)
19 proc = Popen(args, stdin=PIPE, stdout=outpipe, stderr=PIPE, bufsize=1)
21 if outpipe == PIPE:
22 outpipe = proc.stdout
24 return outpipe
27 def run(self):
29 outpipe = self.launch_monitors()
31 records = collections.defaultdict(list)
32 last_records = {} # records indexed by process; used for comparison
34 for line in outpipe:
35 record, process = self.get_record(line)
37 if not record:
38 continue
40 records[process].append(record)
42 if not process in last_records:
43 last_records[process] = record
44 continue
46 if (record['timestamp'] - last_records[process]['timestamp']).seconds <= 0:
47 continue
49 bw = self.get_bandwidth(last_records[process], record)
51 if not bw:
52 continue
54 last_records[process] = record
56 print '%10d / %10d B/s -- %s' % (bw[0], bw[1], process)
59 def get_record(self, line):
60 """
61 parses the given line (output of runmonitor.py) and returns a record
62 which is a dictionary with the keys timestamp, in and out (both in
63 bytes)
64 """
65 match = self.line_regex.match(line)
67 if not match:
68 return None, None
70 process = match.group('proc').strip()
71 bytes_in = int(match.group('in'))
72 bytes_out = int(match.group('out'))
73 record = {'timestamp': datetime.now(), 'in': bytes_in, 'out': bytes_out}
74 return record, process
77 def get_bandwidth(self, rec1, rec2):
78 """
79 returns the mean incoming and outgoing bandwidth used between
80 the two given records.
82 rec1 represents the earlier, rec2 the later record
83 """
84 date_diff = rec2['timestamp'] - rec1['timestamp']
85 in_diff = rec2['in'] - rec1['in']
86 out_diff = rec2['out'] - rec1['out']
88 if not date_diff.seconds:
89 return None
91 in_bw = in_diff / date_diff.seconds
92 out_bw = out_diff / date_diff.seconds
94 return (in_bw, out_bw)