OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 """ | 4 """ |
5 The Value hierarchy provides a way of representing the values measurements | 5 The Value hierarchy provides a way of representing the values measurements |
6 produce such that they can be merged across runs, grouped by page, and output | 6 produce such that they can be merged across runs, grouped by page, and output |
7 to different targets. | 7 to different targets. |
8 | 8 |
9 The core Value concept provides the basic functionality: | 9 The core Value concept provides the basic functionality: |
10 - association with a page, may be none | 10 - association with a page, may be none |
11 - naming and units | 11 - naming and units |
12 - importance tracking [whether a value will show up on a waterfall or output | 12 - importance tracking [whether a value will show up on a waterfall or output |
13 file by default] | 13 file by default] |
| 14 - other metadata, such as a description of what was measured |
14 - default conversion to scalar and string | 15 - default conversion to scalar and string |
15 - merging properties | 16 - merging properties |
16 | 17 |
17 A page may actually run a few times during a single telemetry session. | 18 A page may actually run a few times during a single telemetry session. |
18 Downstream consumers of test results typically want to group these runs | 19 Downstream consumers of test results typically want to group these runs |
19 together, then compute summary statistics across runs. Value provides the | 20 together, then compute summary statistics across runs. Value provides the |
20 Merge* family of methods for this kind of aggregation. | 21 Merge* family of methods for this kind of aggregation. |
21 """ | 22 """ |
22 | 23 |
23 # When combining a pair of Values togehter, it is sometimes ambiguous whether | 24 # When combining a pair of Values togehter, it is sometimes ambiguous whether |
24 # the values should be concatenated, or one should be picked as representative. | 25 # the values should be concatenated, or one should be picked as representative. |
25 # The possible merging policies are listed here. | 26 # The possible merging policies are listed here. |
26 CONCATENATE = 'concatenate' | 27 CONCATENATE = 'concatenate' |
27 PICK_FIRST = 'pick-first' | 28 PICK_FIRST = 'pick-first' |
28 | 29 |
29 # When converting a Value to its buildbot equivalent, the context in which the | 30 # When converting a Value to its buildbot equivalent, the context in which the |
30 # value is being interpreted actually affects the conversion. This is insane, | 31 # value is being interpreted actually affects the conversion. This is insane, |
31 # but there you have it. There are three contexts in which Values are converted | 32 # but there you have it. There are three contexts in which Values are converted |
32 # for use by buildbot, represented by these output-intent values. | 33 # for use by buildbot, represented by these output-intent values. |
33 PER_PAGE_RESULT_OUTPUT_CONTEXT = 'per-page-result-output-context' | 34 PER_PAGE_RESULT_OUTPUT_CONTEXT = 'per-page-result-output-context' |
34 COMPUTED_PER_PAGE_SUMMARY_OUTPUT_CONTEXT = 'merged-pages-result-output-context' | 35 COMPUTED_PER_PAGE_SUMMARY_OUTPUT_CONTEXT = 'merged-pages-result-output-context' |
35 SUMMARY_RESULT_OUTPUT_CONTEXT = 'summary-result-output-context' | 36 SUMMARY_RESULT_OUTPUT_CONTEXT = 'summary-result-output-context' |
36 | 37 |
37 class Value(object): | 38 class Value(object): |
38 """An abstract value produced by a telemetry page test. | 39 """An abstract value produced by a telemetry page test. |
39 """ | 40 """ |
40 def __init__(self, page, name, units, important): | 41 def __init__(self, page, name, units, important, description): |
41 """A generic Value object. | 42 """A generic Value object. |
42 | 43 |
43 Note: page may be given as None to indicate that the value represents | 44 Args: |
44 results multiple pages. | 45 page: A Page object, may be given as None to indicate that the value |
| 46 represents results for multiple pages. |
| 47 name: A value name string, may contain a dot. Values from the same test |
| 48 with the same prefix before the dot may be considered to belong to |
| 49 the same chart. |
| 50 units: A units string. |
| 51 important: Whether the value is "important". Causes the value to appear |
| 52 by default in downstream UIs. |
| 53 description: A string explaining in human-understandable terms what this |
| 54 value represents. |
45 """ | 55 """ |
46 self.page = page | 56 self.page = page |
47 self.name = name | 57 self.name = name |
48 self.units = units | 58 self.units = units |
49 self.important = important | 59 self.important = important |
| 60 self.description = description |
50 | 61 |
51 def IsMergableWith(self, that): | 62 def IsMergableWith(self, that): |
52 return (self.units == that.units and | 63 return (self.units == that.units and |
53 type(self) == type(that) and | 64 type(self) == type(that) and |
54 self.important == that.important) | 65 self.important == that.important) |
55 | 66 |
56 @classmethod | 67 @classmethod |
57 def MergeLikeValuesFromSamePage(cls, values): | 68 def MergeLikeValuesFromSamePage(cls, values): |
58 """Combines the provided list of values into a single compound value. | 69 """Combines the provided list of values into a single compound value. |
59 | 70 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 """ | 172 """ |
162 return self._AsDictImpl() | 173 return self._AsDictImpl() |
163 | 174 |
164 def _AsDictImpl(self): | 175 def _AsDictImpl(self): |
165 d = { | 176 d = { |
166 'name': self.name, | 177 'name': self.name, |
167 'type': self.GetJSONTypeName(), | 178 'type': self.GetJSONTypeName(), |
168 'unit': self.units, | 179 'unit': self.units, |
169 } | 180 } |
170 | 181 |
| 182 if self.description: |
| 183 d['description'] = self.description |
| 184 |
171 if self.page: | 185 if self.page: |
172 d['page_id'] = self.page.id | 186 d['page_id'] = self.page.id |
173 | 187 |
174 return d | 188 return d |
175 | 189 |
176 def AsDictWithoutBaseClassEntries(self): | 190 def AsDictWithoutBaseClassEntries(self): |
177 full_dict = self.AsDict() | 191 full_dict = self.AsDict() |
178 base_dict_keys = set(self._AsDictImpl().keys()) | 192 base_dict_keys = set(self._AsDictImpl().keys()) |
179 | 193 |
180 # Exctracts only entries added by the subclass. | 194 # Extracts only entries added by the subclass. |
181 return dict([(k, v) for (k, v) in full_dict.iteritems() | 195 return dict([(k, v) for (k, v) in full_dict.iteritems() |
182 if k not in base_dict_keys]) | 196 if k not in base_dict_keys]) |
183 | 197 |
184 def ValueNameFromTraceAndChartName(trace_name, chart_name=None): | 198 def ValueNameFromTraceAndChartName(trace_name, chart_name=None): |
185 """Mangles a trace name plus optional chart name into a standard string. | 199 """Mangles a trace name plus optional chart name into a standard string. |
186 | 200 |
187 A value might just be a bareword name, e.g. numPixels. In that case, its | 201 A value might just be a bareword name, e.g. numPixels. In that case, its |
188 chart may be None. | 202 chart may be None. |
189 | 203 |
190 But, a value might also be intended for display with other values, in which | 204 But, a value might also be intended for display with other values, in which |
(...skipping 15 matching lines...) Expand all Loading... |
206 whereas telemetry represents values with a chart_name.trace_name convention, | 220 whereas telemetry represents values with a chart_name.trace_name convention, |
207 where chart_name is optional. | 221 where chart_name is optional. |
208 | 222 |
209 This converts from the telemetry convention to the buildbot convention, | 223 This converts from the telemetry convention to the buildbot convention, |
210 returning a 2-tuple (measurement_name, trace_name). | 224 returning a 2-tuple (measurement_name, trace_name). |
211 """ | 225 """ |
212 if '.' in value_name: | 226 if '.' in value_name: |
213 return value_name.split('.', 1) | 227 return value_name.split('.', 1) |
214 else: | 228 else: |
215 return value_name, value_name | 229 return value_name, value_name |
OLD | NEW |