blob: 9743ed1f6d68b7e30fb7049c7956e3b03509bf6d [file] [log] [blame]
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import json
import os
import urllib
from recipe_engine import recipe_api
_BASE_URL = 'https://chromeperf.appspot.com'
_PINPOINT_BASE_URL = 'https://pinpoint-dot-chromeperf.appspot.com'
class PerfDashboardApi(recipe_api.RecipeApi):
"""Provides steps to take a list of perf points and post them to the
Chromium Perf Dashboard. Can also use the test url for testing purposes."""
def get_skeleton_point(self, test, revision, value, bot=None):
# TODO: masterid is really mastername
assert (test != '')
assert (revision != '')
assert (value != '')
return {
'master': self.m.properties['mastername'],
'bot': bot or self.m.properties['buildername'],
'test': test,
'revision': revision,
'value': value,
'masterid': self.m.properties['mastername'],
'buildername': self.m.properties['buildername'],
'buildnumber': self.m.properties['buildnumber']
}
def add_dashboard_link(self, presentation, test, revision, bot=None):
"""Adds a results-dashboard link to the step presentation.
Must be called from a follow-up function of the step, to which the link
should be added. For a working link, the parameters test, revision and bot
must match to the parameters used to upload points to the dashboard.
Args:
presentation: A step presentation object. Can be obtained by
step_result.presentation from a followup_fn of a step.
test: Slash-separated test path.
revision: The build revision, e.g. got_revision from the update step.
bot: The bot name used for the data on the perf dashboard.
"""
assert presentation
assert test
assert revision
params = urllib.urlencode({
'masters': self.m.properties['mastername'],
'bots': bot or self.m.properties['buildername'],
'tests': test,
'rev': revision,
})
presentation.links['Results Dashboard'] = (
'%s/report?%s' % (_BASE_URL, params))
def set_default_config(self):
# TODO: Remove.
pass
def add_point(self, data, halt_on_failure=False, name=None, **kwargs):
return self.post(name or 'perf dashboard post', '%s/add_point' % _BASE_URL,
{'data': json.dumps(data)}, halt_on_failure, **kwargs)
def post_bisect_results(self, data, halt_on_failure=False, **kwargs):
"""Posts bisect results to Perf Dashboard."""
return self.post('Post bisect results',
'%s/post_bisect_results' % _BASE_URL,
{'data': json.dumps(data)}, halt_on_failure, **kwargs)
def upload_isolate(self, builder_name, change, isolate_server,
isolate_map, halt_on_failure=False, **kwargs):
data = {
'builder_name': builder_name,
'change': json.dumps(change),
'isolate_server': isolate_server,
'isolate_map': json.dumps(isolate_map),
}
return self.post('pinpoint isolate upload',
'%s/api/isolate' % _PINPOINT_BASE_URL,
data, halt_on_failure, **kwargs)
def post(self, name, url, data, halt_on_failure, **kwargs):
"""Send a POST request to a URL with a payload.
Args:
name: The name of the step.
url: The URL to post to.
data: A dict of parameters to send in the body of the request.
halt_on_failure: If True, the step turns purple on failure. Otherwise, it
turns orange.
"""
step_result = self.m.python(
name=name, script=self.resource('post_json.py'), args=[
url, '-i', self.m.json.input(data), '-o', self.m.json.output()],
**kwargs)
response = step_result.json.output
if not response or response['status_code'] != 200: # pragma: no cover
error = response['status_code'] if response else 'None'
reason = ('Failed to post to Perf Dashboard. '
'Error response: %s' % error)
if halt_on_failure:
self.halt(step_result, reason)
else:
self.warning(step_result, reason)
return step_result
def halt(self, step_result, reason): # pragma: no cover
step_result.presentation.step_text = reason
step_result.presentation.status = self.m.step.FAILURE
raise self.m.step.StepFailure(reason)
def warning(self, step_result, reason): # pragma: no cover
step_result.presentation.step_text = reason
step_result.presentation.status = self.m.step.WARNING