Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: tools/telemetry/telemetry/value/trace.py

Issue 441873007: Move timeline and importers to use telemetry.value.TraceValue (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # Copyright 2014 The Chromium 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 import json
6 import numbers
7
8 def _ValidateRawData(raw):
9 if isinstance(raw, basestring):
10 return
11 if isinstance(raw, numbers.Number):
12 return
13
nednguyen 2014/08/05 14:34:34 Can None be raw data? For example: {1:None, 2:'foo
14 if isinstance(raw, list):
15 for r in raw:
16 _ValidateRawData(r)
17 return
18
19 if isinstance(raw, dict):
20 for k,v in raw.iteritems():
21 _ValidateRawData(k)
22 _ValidateRawData(v)
23 return
24
25 raise Exception('%s is not allowed in TraceValue', raw)
nednguyen 2014/08/05 14:34:34 Throwing exception at the leaf level may make it h
26
27
28 # TraceValues have a variety of events in them. These are called "parts" and
29 # aare accessed by name, using the following fixed field names.
nednguyen 2014/08/05 14:34:34 nit: are
30 class TraceValuePart(object):
chrishenry 2014/08/05 23:44:15 Just TracePart? TraceValuePart is a bit ambiguous.
31 def __init__(self, rawFieldName):
32 self.rawFieldName = rawFieldName
chrishenry 2014/08/05 23:44:15 nit: raw_field_name
33
34 def __repr__(self):
35 return 'TraceValuePart("%s")' % self.rawFieldName
36
37 CHROME_TRACE_PART = TraceValuePart('traceEvents')
38 INSPECTOR_TRACE_PART = TraceValuePart('inspectorTimelineEvents')
39 TAB_ID_PART = TraceValuePart('tabIds')
40
41 ALL_TRACE_VALUE_PARTS = set([CHROME_TRACE_PART,
42 INSPECTOR_TRACE_PART,
43 TAB_ID_PART])
44
45 class RawTraceValueHelpersMixin(object):
nednguyen 2014/08/05 14:34:34 Don't you need __init__(self) to define self._raw_
chrishenry 2014/08/05 23:44:16 Does TraceValue and Builder really need to mixin t
46 @property
47 def active_parts(self):
48 return set([p for p in ALL_TRACE_VALUE_PARTS
49 if p.rawFieldName in self._raw_data])
50
51 def HasEventsFor(self, part):
52 assert isinstance(part, TraceValuePart)
53 if part.rawFieldName not in self._raw_data:
54 return False
55 return len(self._raw_data[part.rawFieldName]) > 0
56
57 def GetEventsFor(self, part):
58 assert isinstance(part, TraceValuePart)
59 return self._raw_data[part.rawFieldName]
60
61 @property
62 def metadata_records(self):
63 part_field_names = set([p.rawFieldName for p in ALL_TRACE_VALUE_PARTS])
slamm 2014/08/12 23:11:59 You can build the set with a generator expression
64 for k,v in self._raw_data.iteritems():
chrishenry 2014/08/05 23:44:15 nit: k, v (space after ,)
65 if k in part_field_names:
66 continue
67 yield {
68 'name' : k,
chrishenry 2014/08/05 23:44:15 nit: no space before :
69 'value' : self._raw_data[v]
nednguyen 2014/08/05 14:34:34 'value': v ?
70 }
71
72
73 # TODO(nduca): Make this subclass value. Moving it was a huge enough patch
74 # that the true subclassing will be done in a followup.
75 class TraceValue(RawTraceValueHelpersMixin):
76 def __init__(self, raw_data=None):
77 """Creates a TraceValue from the given data.
78
79 NOTE: raw data must NOT include any non-primitive objects!
80 By design, TraceValue must contain only data that is BOTH serializable
81 to a file, AND restorable once again from that file into a TraceValue
82 without assistance from other classes.
83
84 raw_data can be any of the three standard trace_event formats:
nednguyen 2014/08/05 14:34:34 So we will need something else for video and image
85 1. Trace container format: a json-parseable dict.
86 2. A json-parseable array: assumed to be chrome trace data.
87 3. A json-parseable array missing the final ]: assumed to be
88 chrome trace data.
89 """
90 self._raw_data = {}
91 self._events_are_safely_mutable = False
92 if raw_data == None:
93 return
94
95 _ValidateRawData(raw_data)
96
97 if self._TryInitFromRaw(raw_data):
98 return
99
100 if not isinstance(raw_data, basestring):
chrishenry 2014/08/05 23:44:16 I think it's clearer to refactor TryInitFromRaw an
101 raise ValueError('Unrecognized data format')
102
103 if len(raw_data) == 0:
104 self._raw_data == {}
slamm 2014/08/12 23:11:59 self._raw_data = {} ? Same in _TryInitFromRaw.
105 return
106
107 if raw_data[0] == '[' and raw_data[-1] != ']':
slamm 2014/08/12 23:11:59 Better? if raw_data.startswith('[') and not raw_d
108 if raw_data[-1] == ',':
109 raw_data = raw_data[:-1] + ']'
110 else:
111 raw_data = raw_data + ']'
112
113 raw_data = json.loads(raw_data)
114 if self._TryInitFromRaw(raw_data):
115 self._events_are_safely_mutable = True
116 return
117
118 raise Exception('Unrecognized data format')
119
120 def _TryInitFromRaw(self, raw_data):
121 if isinstance(raw_data, dict):
122 self._raw_data = raw_data
123 return True
124
125 if isinstance(raw_data, list):
126 if len(raw_data) == 0:
127 self._raw_data == {}
128 return True
129
130 self._raw_data = {'traceEvents': raw_data}
nednguyen 2014/08/05 14:34:34 How about self._raw_data = { CHROME_TRACE_PART.raw
131 return True
132
133 return False
134
135 def _SetFromBuilder(self, d):
136 self._raw_data = d
137 self._event_data_is_mutable = True
chrishenry 2014/08/05 23:44:16 Unused? Or do you mean _events_are_safely_mutable?
138
139 @property
140 def events_are_safely_mutable(self):
141 """Returns true if the events in this value are completely sealed.
142
143 Some importers want to take complex fields out of the TraceValue and add
144 them to the model, changing them subtly as they do so. If the TraceValue was
chrishenry 2014/08/05 23:44:16 Do these importers modify the raw data in this Tra
145 constructed with data that is shared with something outside the trace value,
146 for instance a test harness, then this mutation is unexpected. But, if the
147 values are sealed, then mutating the events is a lot faster.
148
149 We know if events are sealed if the value came from a string, or if the
150 value came from
chrishenry 2014/08/05 23:44:16 incomplete sentence?
151 """
152 return self._events_are_safely_mutable
153
154 def Serialize(self, f, gzip_result=False):
155 """Serializes the trace result to a file-like object.
156
157 Always writes in the trace container format."""
158 assert not gzip_result, 'Not implemented'
159 json.dump(self._raw_data, f)
160
161
162 class TraceValueBuilder(RawTraceValueHelpersMixin):
163 def __init__(self):
164 """TraceValueBuilder helps build up of a trace from multiple trace agents.
165
166 TraceValue is supposed to be immutable, but it is useful during recording
167 to have a mutable version. That is TraceValueBuilder.
168 """
169 self._raw_data = {}
170
171 def AsValue(self):
172 if self._raw_data == None:
173 raise Exception('Can only AsValue() once')
174
175 res = TraceValue()
chrishenry 2014/08/05 23:44:16 nit: s/res/value/
176 res._SetFromBuilder(self._raw_data)
177 self._raw_data = None
178 return res
179
180 def AddEventsTo(self, part, events):
181 # Note: this wont work when you call this from multiple browsers.
182 # Each browser's trace_event_impl zeros its timestamps when it writes them
183 # out and doesn't write a timebase that can be used to re-sync them.
chrishenry 2014/08/05 23:44:16 Turn this into pydoc?
184 assert isinstance(part, TraceValuePart)
185 assert isinstance(events, list)
186 if self._raw_data == None:
187 raise Exception('Already called AsValue() on this builder.')
188 existing_events = None
189 existing_events = self._raw_data.get(part.rawFieldName, None)
190 if existing_events == None:
191 existing_events = []
192 self._raw_data[part.rawFieldName] = existing_events
193 existing_events.extend(events)
194
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698