Add possibility of upload check for pc perf tests
Presubmit bot failures are unrelated to the cl. No-Presubmit: True Bug: webrtc:12162 Change-Id: I598d3aea8df9429bdff18b80a400c358fa1461d2 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/186123 Commit-Queue: Andrey Logvin <landrey@webrtc.org> Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Reviewed-by: Artem Titov <titovartem@webrtc.org> Cr-Commit-Position: refs/heads/master@{#32592}
This commit is contained in:

committed by
Commit Bot

parent
7dff9f3a76
commit
728b5d01b0
@ -7,9 +7,11 @@
|
|||||||
# in the file PATENTS. All contributing project authors may
|
# in the file PATENTS. All contributing project authors may
|
||||||
# be found in the AUTHORS file in the root of the source tree.
|
# be found in the AUTHORS file in the root of the source tree.
|
||||||
|
|
||||||
|
import datetime
|
||||||
import httplib2
|
import httplib2
|
||||||
import json
|
import json
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import time
|
||||||
import zlib
|
import zlib
|
||||||
|
|
||||||
from tracing.value import histogram
|
from tracing.value import histogram
|
||||||
@ -59,6 +61,52 @@ def _SendHistogramSet(url, histograms, oauth_token):
|
|||||||
return response, content
|
return response, content
|
||||||
|
|
||||||
|
|
||||||
|
def _WaitForUploadConfirmation(url, oauth_token, upload_token, wait_timeout,
|
||||||
|
wait_polling_period):
|
||||||
|
"""Make a HTTP GET requests to the Performance Dashboard untill upload
|
||||||
|
status is known or the time is out.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
url: URL of Performance Dashboard instance, e.g.
|
||||||
|
"https://chromeperf.appspot.com".
|
||||||
|
oauth_token: An oauth token to use for authorization.
|
||||||
|
upload_token: String that identifies Performance Dashboard and can be used
|
||||||
|
for the status check.
|
||||||
|
wait_timeout: (datetime.timedelta) Maximum time to wait for the
|
||||||
|
confirmation.
|
||||||
|
wait_polling_period: (datetime.timedelta) Performance Dashboard will be
|
||||||
|
polled every wait_polling_period amount of time.
|
||||||
|
"""
|
||||||
|
assert wait_polling_period <= wait_timeout
|
||||||
|
|
||||||
|
headers = {'Authorization': 'Bearer %s' % oauth_token}
|
||||||
|
http = httplib2.Http()
|
||||||
|
|
||||||
|
response = None
|
||||||
|
resp_json = None
|
||||||
|
current_time = datetime.datetime.now()
|
||||||
|
end_time = current_time + wait_timeout
|
||||||
|
next_poll_time = current_time + wait_polling_period
|
||||||
|
while datetime.datetime.now() < end_time:
|
||||||
|
current_time = datetime.datetime.now()
|
||||||
|
if next_poll_time > current_time:
|
||||||
|
time.sleep((next_poll_time - current_time).total_seconds())
|
||||||
|
next_poll_time = datetime.datetime.now() + wait_polling_period
|
||||||
|
|
||||||
|
response, content = http.request(url + '/uploads' + upload_token,
|
||||||
|
method='GET', headers=headers)
|
||||||
|
resp_json = json.loads(content)
|
||||||
|
|
||||||
|
print 'Upload state polled. Response: %s.' % content
|
||||||
|
|
||||||
|
if (response.status != 200 or
|
||||||
|
resp_json['state'] == 'COMPLETED' or
|
||||||
|
resp_json['state'] == 'FAILED'):
|
||||||
|
break
|
||||||
|
|
||||||
|
return response, resp_json
|
||||||
|
|
||||||
|
|
||||||
# TODO(https://crbug.com/1029452): HACKHACK
|
# TODO(https://crbug.com/1029452): HACKHACK
|
||||||
# Remove once we have doubles in the proto and handle -infinity correctly.
|
# Remove once we have doubles in the proto and handle -infinity correctly.
|
||||||
def _ApplyHacks(dicts):
|
def _ApplyHacks(dicts):
|
||||||
@ -113,13 +161,36 @@ def UploadToDashboard(options):
|
|||||||
_DumpOutput(histograms, options.output_json_file)
|
_DumpOutput(histograms, options.output_json_file)
|
||||||
|
|
||||||
oauth_token = _GenerateOauthToken()
|
oauth_token = _GenerateOauthToken()
|
||||||
response, content = _SendHistogramSet(options.dashboard_url, histograms,
|
response, content = _SendHistogramSet(
|
||||||
oauth_token)
|
options.dashboard_url, histograms, oauth_token)
|
||||||
|
|
||||||
|
upload_token = json.loads(content).get('token')
|
||||||
|
if not options.wait_for_upload or not upload_token:
|
||||||
|
print 'Not waiting for upload status confirmation.'
|
||||||
if response.status == 200:
|
if response.status == 200:
|
||||||
print 'Received 200 from dashboard.'
|
print 'Received 200 from dashboard.'
|
||||||
return 0
|
return 0
|
||||||
else:
|
else:
|
||||||
print('Upload failed with %d: %s\n\n%s' %
|
print('Upload failed with %d: %s\n\n%s' % (response.status,
|
||||||
(response.status, response.reason, content))
|
response.reason, content))
|
||||||
|
return 1
|
||||||
|
|
||||||
|
response, resp_json = _WaitForUploadConfirmation(
|
||||||
|
options.dashboard_url,
|
||||||
|
oauth_token,
|
||||||
|
upload_token,
|
||||||
|
datetime.timedelta(seconds=options.wait_timeout_sec),
|
||||||
|
datetime.timedelta(seconds=options.wait_polling_period_sec))
|
||||||
|
|
||||||
|
if response.status != 200 or resp_json['state'] == 'FAILED':
|
||||||
|
print('Upload failed with %d: %s\n\n%s' % (response.status,
|
||||||
|
response.reason,
|
||||||
|
str(resp_json)))
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if resp_json['state'] == 'COMPLETED':
|
||||||
|
print 'Upload completed.'
|
||||||
|
return 0
|
||||||
|
|
||||||
|
print('Upload wasn\'t completed in a given time: %d.', options.wait_timeout)
|
||||||
return 1
|
return 1
|
||||||
|
@ -24,54 +24,54 @@ import sys
|
|||||||
|
|
||||||
def _CreateParser():
|
def _CreateParser():
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('--perf-dashboard-machine-group',
|
parser.add_argument('--perf-dashboard-machine-group', required=True,
|
||||||
required=True,
|
|
||||||
help='The "master" the bots are grouped under. This '
|
help='The "master" the bots are grouped under. This '
|
||||||
'string is the group in the the perf dashboard path '
|
'string is the group in the the perf dashboard path '
|
||||||
'group/bot/perf_id/metric/subtest.')
|
'group/bot/perf_id/metric/subtest.')
|
||||||
parser.add_argument('--bot',
|
parser.add_argument('--bot', required=True,
|
||||||
required=True,
|
|
||||||
help='The bot running the test (e.g. '
|
help='The bot running the test (e.g. '
|
||||||
'webrtc-win-large-tests).')
|
'webrtc-win-large-tests).')
|
||||||
parser.add_argument(
|
parser.add_argument('--test-suite', required=True,
|
||||||
'--test-suite',
|
|
||||||
required=True,
|
|
||||||
help='The key for the test in the dashboard (i.e. what '
|
help='The key for the test in the dashboard (i.e. what '
|
||||||
'you select in the top-level test suite selector in the '
|
'you select in the top-level test suite selector in '
|
||||||
'dashboard')
|
'the dashboard')
|
||||||
parser.add_argument('--webrtc-git-hash',
|
parser.add_argument('--webrtc-git-hash', required=True,
|
||||||
required=True,
|
|
||||||
help='webrtc.googlesource.com commit hash.')
|
help='webrtc.googlesource.com commit hash.')
|
||||||
parser.add_argument('--commit-position',
|
parser.add_argument('--commit-position', type=int, required=True,
|
||||||
type=int,
|
|
||||||
required=True,
|
|
||||||
help='Commit pos corresponding to the git hash.')
|
help='Commit pos corresponding to the git hash.')
|
||||||
parser.add_argument('--build-page-url',
|
parser.add_argument('--build-page-url', required=True,
|
||||||
required=True,
|
|
||||||
help='URL to the build page for this build.')
|
help='URL to the build page for this build.')
|
||||||
parser.add_argument('--dashboard-url',
|
parser.add_argument('--dashboard-url', required=True,
|
||||||
required=True,
|
|
||||||
help='Which dashboard to use.')
|
help='Which dashboard to use.')
|
||||||
parser.add_argument('--input-results-file',
|
parser.add_argument('--input-results-file', type=argparse.FileType(),
|
||||||
type=argparse.FileType(),
|
|
||||||
required=True,
|
required=True,
|
||||||
help='A JSON file with output from WebRTC tests.')
|
help='A JSON file with output from WebRTC tests.')
|
||||||
parser.add_argument('--output-json-file',
|
parser.add_argument('--output-json-file', type=argparse.FileType('w'),
|
||||||
type=argparse.FileType('w'),
|
|
||||||
help='Where to write the output (for debugging).')
|
help='Where to write the output (for debugging).')
|
||||||
parser.add_argument(
|
parser.add_argument('--outdir', required=True,
|
||||||
'--outdir',
|
|
||||||
required=True,
|
|
||||||
help='Path to the local out/ dir (usually out/Default)')
|
help='Path to the local out/ dir (usually out/Default)')
|
||||||
|
parser.add_argument('--wait-for-upload', action='store_true',
|
||||||
|
help='If specified, script will wait untill Chrome '
|
||||||
|
'perf dashboard confirms that the data was succesfully '
|
||||||
|
'proccessed and uploaded')
|
||||||
|
parser.add_argument('--wait-timeout-sec', type=int, default=1200,
|
||||||
|
help='Used only if wait-for-upload is True. Maximum '
|
||||||
|
'amount of time in seconds that the script will wait '
|
||||||
|
'for the confirmation.')
|
||||||
|
parser.add_argument('--wait-polling-period-sec', type=int, default=120,
|
||||||
|
help='Used only if wait-for-upload is True. Status '
|
||||||
|
'will be requested from the Dashboard every '
|
||||||
|
'wait-polling-period-sec seconds.')
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
def _ConfigurePythonPath(options):
|
def _ConfigurePythonPath(options):
|
||||||
# We just yank the python scripts we require into the PYTHONPATH. You could
|
# We just yank the python scripts we require into the PYTHONPATH. You could
|
||||||
# also imagine a solution where we use for instance protobuf:py_proto_runtime
|
# also imagine a solution where we use for instance
|
||||||
# to copy catapult and protobuf code to out/. This is the convention in
|
# protobuf:py_proto_runtime to copy catapult and protobuf code to out/.
|
||||||
# Chromium and WebRTC python scripts. We do need to build histogram_pb2
|
# This is the convention in Chromium and WebRTC python scripts. We do need
|
||||||
# however, so that's why we add out/ to sys.path below.
|
# to build histogram_pb2 however, so that's why we add out/ to sys.path
|
||||||
|
# below.
|
||||||
#
|
#
|
||||||
# It would be better if there was an equivalent to py_binary in GN, but
|
# It would be better if there was an equivalent to py_binary in GN, but
|
||||||
# there's not.
|
# there's not.
|
||||||
@ -84,8 +84,9 @@ def _ConfigurePythonPath(options):
|
|||||||
sys.path.insert(
|
sys.path.insert(
|
||||||
0, os.path.join(checkout_root, 'third_party', 'protobuf', 'python'))
|
0, os.path.join(checkout_root, 'third_party', 'protobuf', 'python'))
|
||||||
|
|
||||||
# The webrtc_dashboard_upload gn rule will build the protobuf stub for python,
|
# The webrtc_dashboard_upload gn rule will build the protobuf stub for
|
||||||
# so put it in the path for this script before we attempt to import it.
|
# python, so put it in the path for this script before we attempt to import
|
||||||
|
# it.
|
||||||
histogram_proto_path = os.path.join(options.outdir, 'pyproto', 'tracing',
|
histogram_proto_path = os.path.join(options.outdir, 'pyproto', 'tracing',
|
||||||
'tracing', 'proto')
|
'tracing', 'proto')
|
||||||
sys.path.insert(0, histogram_proto_path)
|
sys.path.insert(0, histogram_proto_path)
|
||||||
|
Reference in New Issue
Block a user