blob: 34f1b01df3b610acb49c0df634c4dea8eebf019d [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:
50 self.HandleLine(line)
51
52 def HandleLine(self, line):
53 """
54 Parses a line from a log file and adds the data to the plot data.
55
56 Args:
57 line: str, The line from the log file to parse
58
59 Returns:
60 None
61 """
62 pline = LogEntry(line)
63 pline_data = None
64
65 for key in self.signal:
66 value = self.signal[key]
67 binary = key[0]
68 struct_instance_name = key[1]
69 data_search_path = key[2]
70 boolean_multiplier = None
71
72 # If the plot definition line ends with a "-b X" where X is a number then
73 # that number gets drawn when the value is True. Zero gets drawn when the
74 # value is False.
75 if len(data_search_path) >= 2 and data_search_path[-2] == '-b':
76 boolean_multiplier = float(data_search_path[-1])
77 data_search_path = data_search_path[:-2]
78
79 # Make sure that we're looking at the right binary structure instance.
80 if binary == pline.name:
81 if pline.msg.startswith(struct_instance_name + ': '):
82 # Parse the structure once.
83 if pline_data is None:
84 _, _, pline_data = pline.ParseStruct()
85 # Traverse the structure as specified in `data_search_path`.
86 # This lets the user access very deeply nested structures.
87 data = pline_data
88 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)