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

Side by Side Diff: scripts/slave/results_dashboard.py

Issue 545803002: Update buildbots to parse new telemetry JSON format. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/build.git@master
Patch Set: Addressed review comments Created 6 years, 3 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
« no previous file with comments | « scripts/slave/performance_log_processor.py ('k') | scripts/slave/runtest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Functions for adding results to perf dashboard.""" 6 """Functions for adding results to perf dashboard."""
7 7
8 import calendar 8 import calendar
9 import datetime 9 import datetime
10 import httplib 10 import httplib
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 Each dictionary has the keys "master", "bot", "test", "value", "revision". 171 Each dictionary has the keys "master", "bot", "test", "value", "revision".
172 The full details of this format are described at http://goo.gl/TcJliv. 172 The full details of this format are described at http://goo.gl/TcJliv.
173 """ 173 """
174 results = [] 174 results = []
175 175
176 # The master name used for the dashboard is the CamelCase name returned by 176 # The master name used for the dashboard is the CamelCase name returned by
177 # GetActiveMaster(), and not the canonical master name with dots. 177 # GetActiveMaster(), and not the canonical master name with dots.
178 master = slave_utils.GetActiveMaster() 178 master = slave_utils.GetActiveMaster()
179 179
180 for chart_name, chart_data in sorted(charts.items()): 180 for chart_name, chart_data in sorted(charts.items()):
181 revision, revision_columns = _RevisionNumberColumns(chart_data, master) 181 revision, default_rev, revision_columns = _RevisionNumberColumns(
182 chart_data, master, 'r_')
182 183
183 for trace_name, trace_values in sorted(chart_data['traces'].items()): 184 for trace_name, trace_values in sorted(chart_data['traces'].items()):
184 is_important = trace_name in chart_data.get('important', []) 185 is_important = trace_name in chart_data.get('important', [])
185 test_path = _TestPath(test_name, chart_name, trace_name) 186 test_path = _TestPath(test_name, chart_name, trace_name)
186 result = { 187 result = {
187 'master': master, 188 'master': master,
188 'bot': bot, 189 'bot': bot,
189 'test': test_path, 190 'test': test_path,
190 'revision': revision, 191 'revision': revision,
191 'masterid': mastername, 192 'masterid': mastername,
192 'buildername': buildername, 193 'buildername': buildername,
193 'buildnumber': buildnumber, 194 'buildnumber': buildnumber,
194 'supplemental_columns': {} 195 'supplemental_columns': {}
195 } 196 }
197 if default_rev:
198 supplemental_columns['a_default_rev'] = default_rev
196 199
197 # Add the supplemental_columns values that were passed in after the 200 # Add the supplemental_columns values that were passed in after the
198 # calculated revision column values so that these can be overwritten. 201 # calculated revision column values so that these can be overwritten.
199 result['supplemental_columns'].update(revision_columns) 202 result['supplemental_columns'].update(revision_columns)
200 result['supplemental_columns'].update(supplemental_columns) 203 result['supplemental_columns'].update(supplemental_columns)
201 204
202 # Check whether this result is itself a time series (e.g. Endure result). 205 # Check whether this result is itself a time series (e.g. Endure result).
203 # If so add the key "data", otherwise add "value" and "error". 206 # If so add the key "data", otherwise add "value" and "error".
204 have_multi_value_data = False 207 have_multi_value_data = False
205 for value in trace_values: 208 for value in trace_values:
(...skipping 13 matching lines...) Expand all
219 if chart_data.get('stack'): 222 if chart_data.get('stack'):
220 result['stack'] = chart_data['stack'] 223 result['stack'] = chart_data['stack']
221 if is_important: 224 if is_important:
222 result['important'] = True 225 result['important'] = True
223 226
224 results.append(result) 227 results.append(result)
225 228
226 return results 229 return results
227 230
228 231
229 def _RevisionNumberColumns(data, master): 232 def MakeDashboardJsonV1(chart_json, revision_data, bot, mastername,
233 buildername, buildnumber, supplemental_dict, is_ref):
234 """Generates Dashboard JSON in the new Telemetry format.
235
236 Args:
237 chart_json: The json output by telemetry
238 revision_data: Data about revisions to include in the upload
239 bot: A string which comes from perf_id, e.g. linux-release.
240 mastername: Buildbot master name, e.g. chromium.perf.
241 buildername: Builder name (for stdio links).
242 buildnumber: Build number (for stdio links).
243 supplemental_columns: A dictionary of extra data to send with a point.
244 is_ref: True if this is a reference build, False otherwise.
245
246 Returns:
247 A dictionary in the format accepted by the perf dashboard.
248 """
249 if not chart_json:
250 print 'Error: No json output from telemetry.'
251 print '@@@STEP_EXCEPTION@@@'
252 # The master name used for the dashboard is the CamelCase name returned by
253 # GetActiveMaster(), and not the canonical master name with dots.
254 master = slave_utils.GetActiveMaster()
255 point_id, default_rev, versions = _RevisionNumberColumns(
256 revision_data, master, '')
257 supplemental_columns = {}
258 if default_rev:
259 supplemental_columns['default_rev'] = default_rev
260 for key in supplemental_dict:
261 supplemental_columns[key.replace('a_', '', 1)] = supplemental_dict[key]
262 fields = {
263 'master': master,
264 'bot': bot,
265 'masterid': mastername,
266 'buildername': buildername,
267 'buildnumber': buildnumber,
268 'point_id': point_id,
269 'supplemental': supplemental_columns,
270 'versions': versions,
271 'chart_data': chart_json,
272 'is_ref': is_ref,
273 }
274 return fields
275
276
277 def _GetTimestamp():
278 """Get the Unix timestamp for the current time."""
279 return int(calendar.timegm(datetime.datetime.utcnow().utctimetuple()))
280
281
282 def _RevisionNumberColumns(data, master, prefix):
230 """Get the revision number and revision-related columns from the given data. 283 """Get the revision number and revision-related columns from the given data.
231 284
232 Args: 285 Args:
233 data: A dict of information from one line of the log file. 286 data: A dict of information from one line of the log file.
234 master: The name of the buildbot master. 287 master: The name of the buildbot master.
288 prefix: Prefix for keys. 'r_' for old-style json, '' for telemetry json.
235 289
236 Returns: 290 Returns:
237 A pair with the revision number (which must be an int), and a dict of 291 A 3-tuple with the revision number (which must be an int), the default rev
238 version-related supplemental columns. 292 name, and a dict of version-related supplemental columns.
239 """ 293 """
240 def GetTimestamp():
241 """Get the Unix timestamp for the current time."""
242 return int(calendar.timegm(datetime.datetime.utcnow().utctimetuple()))
243
244 revision_supplemental_columns = {} 294 revision_supplemental_columns = {}
295 default_rev = None
245 296
246 # The dashboard requires points' x-values to be integers, and points are 297 # The dashboard requires points' x-values to be integers, and points are
247 # ordered by this. If the revision can't be parsed as an int, assume that 298 # ordered by this. If the revision can't be parsed as an int, assume that
248 # it's a git hash and use timestamp as the x-value. 299 # it's a git hash and use timestamp as the x-value.
249 git_hash = None 300 git_hash = None
250 try: 301 try:
251 revision = int(data['rev']) 302 revision = int(data['rev'])
252 except ValueError: 303 except ValueError:
253 # The dashboard requires ordered integer revision numbers. If the revision 304 # The dashboard requires ordered integer revision numbers. If the revision
254 # is not an integer, assume it's a git hash and send a timestamp. 305 # is not an integer, assume it's a git hash and send a timestamp.
255 revision = GetTimestamp() 306 revision = _GetTimestamp()
256 git_hash = data['rev'] 307 git_hash = data['rev']
257 308
258 # Add Chromium version if it was specified, and use timestamp as x-value. 309 # Add Chromium version if it was specified, and use timestamp as x-value.
259 if 'ver' in data and data['ver'] != 'undefined': 310 if 'ver' in data and data['ver'] != 'undefined':
260 revision_supplemental_columns['r_chrome_version'] = data['ver'] 311 revision_supplemental_columns[prefix + 'chrome_version'] = data['ver']
261 revision_supplemental_columns['a_default_rev'] = 'r_chrome_version' 312 default_rev = 'r_chrome_version'
262 revision = GetTimestamp() 313 revision = _GetTimestamp()
263 314
264 # Blink builds can have the same chromium revision for two builds. So 315 # Blink builds can have the same chromium revision for two builds. So
265 # order them by timestamp to get them to show on the dashboard in the 316 # order them by timestamp to get them to show on the dashboard in the
266 # order they were built. 317 # order they were built.
267 if master in ['ChromiumWebkit', 'Oilpan']: 318 if master in ['ChromiumWebkit', 'Oilpan']:
268 if not git_hash: 319 if not git_hash:
269 revision_supplemental_columns['r_chromium_svn'] = revision 320 revision_supplemental_columns[prefix + 'chromium_svn'] = revision
270 revision = GetTimestamp() 321 revision = _GetTimestamp()
271 322
272 # Regardless of what the master is, if the given "rev" can't be parsed as 323 # Regardless of what the master is, if the given "rev" can't be parsed as
273 # an int, we're assuming that it's a git hash. 324 # an int, we're assuming that it's a git hash.
274 if git_hash: 325 if git_hash:
275 revision_supplemental_columns['r_chromium'] = git_hash 326 revision_supplemental_columns[prefix + 'chromium'] = git_hash
276 327
277 # For Oilpan, send the webkit_rev as r_oilpan since we are getting 328 # For Oilpan, send the webkit_rev as r_oilpan since we are getting
278 # the oilpan branch revision instead of the Blink trunk revision 329 # the oilpan branch revision instead of the Blink trunk revision
279 # and set r_oilpan to be the dashboard default revision. 330 # and set r_oilpan to be the dashboard default revision.
280 if master == 'Oilpan': 331 if master == 'Oilpan':
281 revision_supplemental_columns['r_oilpan'] = data['webkit_rev'] 332 revision_supplemental_columns[prefix + 'oilpan'] = data['webkit_rev']
282 revision_supplemental_columns['a_default_rev'] = 'r_oilpan' 333 default_rev = 'r_oilpan'
283 else: 334 else:
284 # For other revision data, add it if it's present and not undefined: 335 # For other revision data, add it if it's present and not undefined:
285 for key in ['webkit_rev', 'webrtc_rev', 'v8_rev']: 336 for key in ['webkit_rev', 'webrtc_rev', 'v8_rev']:
286 if key in data and data[key] != 'undefined': 337 if key in data and data[key] != 'undefined':
287 revision_supplemental_columns['r_' + key] = data[key] 338 revision_supplemental_columns[prefix + key] = data[key]
288 339
289 # If possible, also send the git hash. 340 # If possible, also send the git hash.
290 # If no other "default revision" type is specified already, use the git hash. 341 # If no other "default revision" type is specified already, use the git hash.
291 # This will change how it is displayed on the perf dashboard. 342 # This will change how it is displayed on the perf dashboard.
292 if 'git_revision' in data and data['git_revision'] != 'undefined': 343 if 'git_revision' in data and data['git_revision'] != 'undefined':
293 revision_supplemental_columns['r_chromium'] = data['git_revision'] 344 revision_supplemental_columns[prefix + 'chromium'] = data['git_revision']
294 if 'a_default_rev' not in revision_supplemental_columns: 345 if not default_rev:
295 revision_supplemental_columns['a_default_rev'] = 'r_chromium' 346 default_rev = 'r_chromium'
296 347
297 return revision, revision_supplemental_columns 348 return revision, default_rev, revision_supplemental_columns
298 349
299 350
300 def _TestPath(test_name, chart_name, trace_name): 351 def _TestPath(test_name, chart_name, trace_name):
301 """Get the slash-separated test path to send. 352 """Get the slash-separated test path to send.
302 353
303 Args: 354 Args:
304 test: Test name. Typically, this will be a top-level 'test suite' name. 355 test: Test name. Typically, this will be a top-level 'test suite' name.
305 chart_name: Name of a chart where multiple trace lines are grouped. If the 356 chart_name: Name of a chart where multiple trace lines are grouped. If the
306 chart name is the same as the trace name, that signifies that this is 357 chart name is the same as the trace name, that signifies that this is
307 the main trace for the chart. 358 the main trace for the chart.
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 def _LinkAnnotation(url, data): 411 def _LinkAnnotation(url, data):
361 """Prints a link annotation with a link to the dashboard if possible. 412 """Prints a link annotation with a link to the dashboard if possible.
362 413
363 Args: 414 Args:
364 url: The Performance Dashboard URL, e.g. "https://chromeperf.appspot.com" 415 url: The Performance Dashboard URL, e.g. "https://chromeperf.appspot.com"
365 data: The data that's being sent to the dashboard. 416 data: The data that's being sent to the dashboard.
366 417
367 Returns: 418 Returns:
368 An annotation to print, or None. 419 An annotation to print, or None.
369 """ 420 """
370 if not data or type(data) is not list: 421 if not data:
371 return None 422 return None
372 point = data[0] 423 if isinstance(data, list):
424 master, bot, test, revision = (
425 data[0]['master'], data[0]['bot'], data[0]['test'], data[0]['revision'])
426 else:
427 master, bot, test, revision = (
428 data['master'], data['bot'], data['chart_data']['benchmark_name'],
429 data['point_id'])
373 results_link = url + RESULTS_LINK_PATH % ( 430 results_link = url + RESULTS_LINK_PATH % (
374 urllib.quote(point['master']), 431 urllib.quote(master), urllib.quote(bot), urllib.quote(test.split('/')[0]),
375 urllib.quote(point['bot']), 432 revision)
376 urllib.quote(point['test'].split('/')[0]),
377 point['revision'])
378 return '@@@STEP_LINK@%s@%s@@@' % ('Results Dashboard', results_link) 433 return '@@@STEP_LINK@%s@%s@@@' % ('Results Dashboard', results_link)
OLDNEW
« no previous file with comments | « scripts/slave/performance_log_processor.py ('k') | scripts/slave/runtest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698