blob: c59487bc32ab757b59fef9e7a4a177c21ac3799c [file] [log] [blame]
Dave Smithacbca192016-03-06 15:27:23 -08001#!/usr/bin/python3
2
3import collections
4from logentry import LogEntry
5
6class Dataset(object):
7 def __init__(self):
8 self.time = []
9 self.data = []
10
11 def Add(self, time, data):
12 self.time.append(time)
13 self.data.append(data)
14
15class CollectingLogReader(object):
16 """
17 Reads log files and collected requested data.
18 """
19 def __init__(self):
20 self.signal = collections.OrderedDict()
21
22 def Add(self, binary, struct_instance_name, *data_search_path):
23 """
24 Specifies a specific piece of data to collect
25
26 Args:
27 binary: str, The name of the executable that generated the log.
28 struct_instance_name: str, The name of the struct instance whose data
29 contents should be collected.
30 data_search_path: [str], The path into the struct of the exact piece of
31 data to collect.
32
33 Returns:
34 None
35 """
36 self.signal[(binary, struct_instance_name, data_search_path)] = Dataset()
37
38 def HandleFile(self, f):
39 """
40 Parses the specified log file.
41
42 Args:
43 f: str, The filename of the log whose data to parse.
44
45 Returns:
46 None
47 """
48 with open(f, 'r') as fd:
49 for line in fd:
Dave Smith41e3b792016-03-07 17:45:50 -080050 try:
51 self.HandleLine(line)
52 except Exception as ex:
53 # It's common for the last line of the file to be malformed.
54 print("Ignoring malformed log entry: ", line)
Dave Smithacbca192016-03-06 15:27:23 -080055
56 def HandleLine(self, line):
57 """
58 Parses a line from a log file and adds the data to the plot data.
59
60 Args:
61 line: str, The line from the log file to parse
62
63 Returns:
64 None
65 """
66 pline = LogEntry(line)
Dave Smithacbca192016-03-06 15:27:23 -080067
68 for key in self.signal:
69 value = self.signal[key]
70 binary = key[0]
71 struct_instance_name = key[1]
72 data_search_path = key[2]
73 boolean_multiplier = None
74
75 # If the plot definition line ends with a "-b X" where X is a number then
76 # that number gets drawn when the value is True. Zero gets drawn when the
77 # value is False.
78 if len(data_search_path) >= 2 and data_search_path[-2] == '-b':
79 boolean_multiplier = float(data_search_path[-1])
80 data_search_path = data_search_path[:-2]
81
82 # Make sure that we're looking at the right binary structure instance.
83 if binary == pline.name:
84 if pline.msg.startswith(struct_instance_name + ': '):
Dave Smithacbca192016-03-06 15:27:23 -080085 # Traverse the structure as specified in `data_search_path`.
86 # This lets the user access very deeply nested structures.
Dave Smith41e3b792016-03-07 17:45:50 -080087 _, _, data = pline.ParseStruct()
Dave Smithacbca192016-03-06 15:27:23 -080088 for path in data_search_path:
89 data = data[path]
90
91 if boolean_multiplier is not None:
92 if data == 'T':
93 value.Add(pline.time, boolean_multiplier)
94 else:
95 value.Add(pline.time, 0)
96 else:
97 value.Add(pline.time, data)