blob: d04374a5134ef70586043aaa1f172488da37cf06 [file] [log] [blame]
Patrik Höglundcb0b8742019-11-18 13:46:38 +01001#!/usr/bin/env python
2# Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3#
4# Use of this source code is governed by a BSD-style license
5# that can be found in the LICENSE file in the root of the source
6# tree. An additional intellectual property rights grant can be found
7# in the file PATENTS. All contributing project authors may
8# be found in the AUTHORS file in the root of the source tree.
9
10"""Converts and uploads results to the Chrome perf dashboard.
11
12This conversion step is needed because test/testsupport/perf_test.cc can't
13output histograms natively. There is, unfortunately, no C++ API for histograms.
14This script is in python so it can depend on Catapult's python API instead.
15See histogram_util.py for how this is done. We should move to the C++ API and
16delete the scripts in this dir as soon as there is a C++ API (less conversions =
17easier to understand).
18
19This script can't be in recipes, because we can't access the catapult APIs from
20there. It needs to be here source-side.
21
22This script is adapted from the downstream variant like this:
23 * Follows upstream naming conventions.
24 * Downstream-only parameters and concepts go away.
25 * oAuth tokens are generated by luci-auth.
26"""
27
28import argparse
29import httplib2
30import json
31import sys
32import subprocess
33import zlib
34
35import histogram_util
36
37
38def _GenerateOauthToken():
39 args = ['luci-auth', 'token']
40 p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
41 if p.wait() == 0:
42 output = p.stdout.read()
43 return output.strip()
44 else:
45 raise RuntimeError(
46 'Error generating authentication token.\nStdout: %s\nStderr:%s' %
47 (p.stdout.read(), p.stderr.read()))
48
49
50def _SendHistogramSetJson(url, histogram_json, oauth_token):
51 """Make a HTTP POST with the given JSON to the Performance Dashboard.
52
53 Args:
54 url: URL of Performance Dashboard instance, e.g.
55 "https://chromeperf.appspot.com".
56 histogram_json: a JSON object that contains the data to be sent.
57 oauth_token: An oauth token to use for authorization.
58 """
59 headers = {'Authorization': 'Bearer %s' % oauth_token}
60 serialized = json.dumps(histogram_json.AsDicts(), indent=4)
61 data = zlib.compress(serialized)
62
63 http = httplib2.Http()
64 response, content = http.request(url + '/add_histograms', method='POST',
65 body=data, headers=headers)
66 return response, content
67
68
69def _LoadHistogramSetJson(options):
70 with options.input_results_file as f:
71 json_data = json.load(f)
72
73 histograms = histogram_util.LoadHistograms(json_data)
74 hs = histogram_util.MakeWebRtcHistogramSet(
75 stats=histograms,
76 commit_pos=options.commit_position,
77 commit_hash=options.webrtc_git_hash,
78 master=options.perf_dashboard_machine_group,
79 bot=options.bot,
80 test_suite=options.test_suite,
81 build_url=options.build_page_url)
82
83 return hs
84
85
86def _CreateParser():
87 parser = argparse.ArgumentParser()
88 parser.add_argument('--perf-dashboard-machine-group', required=True,
89 help='The "master" the bots are grouped under. This '
90 'string is the group in the the perf dashboard path '
91 'group/bot/perf_id/metric/subtest.')
92 parser.add_argument('--bot', required=True,
93 help='The bot running the test (e.g. '
94 'webrtc-win-large-tests).')
95 parser.add_argument('--test-suite', required=True,
96 help='The key for the test in the dashboard (i.e. what '
97 'you select in the top-level test suite selector in the '
98 'dashboard')
99 parser.add_argument('--webrtc-git-hash', required=True,
100 help='webrtc.googlesource.com commit hash.')
101 parser.add_argument('--commit-position', type=int, required=True,
102 help='Commit pos corresponding to the git hash.')
103 parser.add_argument('--build-page-url', required=True,
104 help='URL to the build page for this build.')
105 parser.add_argument('--dashboard-url', required=True,
106 help='Which dashboard to use.')
107 parser.add_argument('--input-results-file', type=argparse.FileType(),
108 required=True,
109 help='A JSON file with output from WebRTC tests.')
110 parser.add_argument('--output-json-file', type=argparse.FileType('w'),
111 help='Where to write the output (for debugging).')
112 return parser
113
114
115def main(args):
116 parser = _CreateParser()
117 options = parser.parse_args(args)
118
119 histogram_json = _LoadHistogramSetJson(options)
120
121 if options.output_json_file:
122 with options.output_json_file as output_file:
123 json.dump(histogram_json.AsDicts(), output_file, indent=4)
124
125 oauth_token = _GenerateOauthToken()
126 response, content = _SendHistogramSetJson(
127 options.dashboard_url, histogram_json, oauth_token)
128
129 if response.status == 200:
130 return 0
131 else:
132 print("Upload failed with %d: %s\n\n%s" % (response.status, response.reason,
133 content))
134 return 1
135
136
137if __name__ == '__main__':
138 sys.exit(main(sys.argv[1:]))