Prepare uploader to be used as a 'merge script'.

* Don't exit by throwing exceptions.
* Rely on a dataclass instead of argument list.
* Prepare to remove arg wait_upload because it's always true.
* Remove unused args wait_timeout_sec and wait_timeout_secwait_polling_period_sec.

Bug: webrtc:13806
Change-Id: I0879fa7fd22c72f5b174f8823bdd51d49f1f140b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/255320
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Jeremy Leconte <jleconte@google.com>
Reviewed-by: Andrey Logvin <landrey@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36193}
This commit is contained in:
Jeremy Leconte
2022-03-14 15:22:37 +01:00
committed by WebRTC LUCI CQ
parent 8ca06137dc
commit 2c4a4472a5
2 changed files with 75 additions and 32 deletions

View File

@ -14,6 +14,7 @@ import subprocess
import time
import zlib
import dataclasses
import httplib2
from tracing.value import histogram
@ -22,6 +23,41 @@ from tracing.value.diagnostics import generic_set
from tracing.value.diagnostics import reserved_infos
@dataclasses.dataclass
class UploaderOptions():
"""Required information to upload perf metrics.
Attributes:
perf_dashboard_machine_group: The "master" the bots are grouped under.
This string is the group in the the perf dashboard path
group/bot/perf_id/metric/subtest.
bot: The bot running the test (e.g. webrtc-win-large-tests).
test_suite: The key for the test in the dashboard (i.e. what you select
in the top-level test suite selector in the dashboard
webrtc_git_hash: webrtc.googlesource.com commit hash.
commit_position: Commit pos corresponding to the git hash.
build_page_url: URL to the build page for this build.
dashboard_url: Which dashboard to use.
input_results_file: A HistogramSet proto file coming from WebRTC tests.
output_json_file: Where to write the output (for debugging).
wait_timeout_sec: Maximum amount of time in seconds that the script will
wait for the confirmation.
wait_polling_period_sec: Status will be requested from the Dashboard
every wait_polling_period_sec seconds.
"""
perf_dashboard_machine_group: str
bot: str
test_suite: str
webrtc_git_hash: str
commit_position: int
build_page_url: str
dashboard_url: str
input_results_file: str
output_json_file: str
wait_timeout_sec: datetime.timedelta = datetime.timedelta(seconds=1200)
wait_polling_period_sec: datetime.timedelta = datetime.timedelta(seconds=120)
def _GenerateOauthToken():
args = ['luci-auth', 'token']
p = subprocess.Popen(args,
@ -195,7 +231,7 @@ def _ApplyHacks(dicts):
def _LoadHistogramSetFromProto(options):
hs = histogram_set.HistogramSet()
with options.input_results_file as f:
with open(options.input_results_file, 'rb') as f:
hs.ImportProto(f.read())
return hs
@ -217,11 +253,11 @@ def _AddBuildInfo(histograms, options):
def _DumpOutput(histograms, output_file):
with output_file:
json.dump(_ApplyHacks(histograms.AsDicts()), output_file, indent=4)
with open(output_file, 'wb') as f:
json.dump(_ApplyHacks(histograms.AsDicts()), f, indent=4)
def UploadToDashboard(options):
def UploadToDashboardImpl(options):
histograms = _LoadHistogramSetFromProto(options)
_AddBuildInfo(histograms, options)
@ -236,15 +272,14 @@ def UploadToDashboard(options):
return 1
upload_token = json.loads(content).get('token')
if not options.wait_for_upload or not upload_token:
if not upload_token:
print(('Received 200 from dashboard. ',
'Not waiting for the upload status confirmation.'))
return 0
response, resp_json = _WaitForUploadConfirmation(
options.dashboard_url, upload_token,
datetime.timedelta(seconds=options.wait_timeout_sec),
datetime.timedelta(seconds=options.wait_polling_period_sec))
options.dashboard_url, upload_token, options.wait_timeout_sec,
options.wait_polling_period_sec)
if ((resp_json and resp_json['state'] == 'COMPLETED')
or _CheckFullUploadInfo(options.dashboard_url, upload_token)):
@ -260,6 +295,15 @@ def UploadToDashboard(options):
print('Upload failed.')
return 1
print(('Upload wasn\'t completed in a given time: %d seconds.' %
print(('Upload wasn\'t completed in a given time: %s seconds.' %
options.wait_timeout_sec))
return 1
def UploadToDashboard(options):
try:
exit_code = UploadToDashboardImpl(options)
except RuntimeError as e:
print(e)
return 2
return exit_code

View File

@ -32,9 +32,9 @@ def _CreateParser():
parser = argparse.ArgumentParser()
parser.add_argument('--perf-dashboard-machine-group',
required=True,
help='The "master" the bots are grouped under. This '
'string is the group in the the perf dashboard path '
'group/bot/perf_id/metric/subtest.')
help='The "machine_group" the bots are grouped under.'
'This string is the group in the the perf dashboard '
'path group/bot/perf_id/metric/subtest.')
parser.add_argument('--bot',
required=True,
help='The bot running the test (e.g. '
@ -68,27 +68,14 @@ def _CreateParser():
parser.add_argument('--outdir',
required=True,
help='Path to the local out/ dir (usually out/Default)')
# TODO(crbug.com/webrtc/13806): Remove this argument.
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.')
help='DEPRECATED: this option will soon be removed')
return parser
def _ConfigurePythonPath(options):
def _ConfigurePythonPath(outdir):
# 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 to copy catapult and protobuf code to out/.
@ -110,8 +97,8 @@ def _ConfigurePythonPath(options):
# The webrtc_dashboard_upload gn rule will build the protobuf stub for
# 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',
'tracing', 'proto')
histogram_proto_path = os.path.join(outdir, 'pyproto', 'tracing', 'tracing',
'proto')
sys.path.insert(0, histogram_proto_path)
# Fail early in case the proto hasn't been built.
@ -127,11 +114,23 @@ def main(args):
parser = _CreateParser()
options = parser.parse_args(args)
_ConfigurePythonPath(options)
_ConfigurePythonPath(options.outdir)
import catapult_uploader
return catapult_uploader.UploadToDashboard(options)
uploader_options = catapult_uploader.UploaderOptions(
perf_dashboard_machine_group=options.perf_dashboard_machine_group,
bot=options.bot,
test_suite=options.test_suite,
webrtc_git_hash=options.webrtc_git_hash,
commit_position=options.commit_position,
build_page_url=options.build_page_url,
dashboard_url=options.dashboard_url,
input_results_file=options.input_results_file,
output_json_file=options.output_json_file,
)
return catapult_uploader.UploadToDashboard(uploader_options)
if __name__ == '__main__':