blob: d9bc0a889576fe19a4e37dfea7543b58735905cb [file] [log] [blame]
Patrik Höglund0569a122020-03-13 12:26:42 +01001#!/usr/bin/env python
2# Copyright (c) 2020 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
Patrik Höglund0569a122020-03-13 12:26:42 +010010import httplib2
11import json
12import subprocess
13import zlib
14
Patrik Höglund620bed12020-03-17 09:59:10 +010015from tracing.value import histogram
Patrik Höglund0569a122020-03-13 12:26:42 +010016from tracing.value import histogram_set
17from tracing.value.diagnostics import generic_set
18from tracing.value.diagnostics import reserved_infos
19
20
21def _GenerateOauthToken():
Mirko Bonadei8cc66952020-10-30 10:13:45 +010022 args = ['luci-auth', 'token']
23 p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
24 if p.wait() == 0:
25 output = p.stdout.read()
26 return output.strip()
27 else:
28 raise RuntimeError(
29 'Error generating authentication token.\nStdout: %s\nStderr:%s' %
30 (p.stdout.read(), p.stderr.read()))
Patrik Höglund0569a122020-03-13 12:26:42 +010031
32
33def _SendHistogramSet(url, histograms, oauth_token):
Mirko Bonadei8cc66952020-10-30 10:13:45 +010034 """Make a HTTP POST with the given JSON to the Performance Dashboard.
Patrik Höglund0569a122020-03-13 12:26:42 +010035
36 Args:
37 url: URL of Performance Dashboard instance, e.g.
38 "https://chromeperf.appspot.com".
39 histograms: a histogram set object that contains the data to be sent.
40 oauth_token: An oauth token to use for authorization.
41 """
Mirko Bonadei8cc66952020-10-30 10:13:45 +010042 headers = {'Authorization': 'Bearer %s' % oauth_token}
Patrik Höglund0569a122020-03-13 12:26:42 +010043
Mirko Bonadei8cc66952020-10-30 10:13:45 +010044 serialized = json.dumps(_ApplyHacks(histograms.AsDicts()), indent=4)
Patrik Höglund0569a122020-03-13 12:26:42 +010045
Mirko Bonadei8cc66952020-10-30 10:13:45 +010046 if url.startswith('http://localhost'):
47 # The catapult server turns off compression in developer mode.
48 data = serialized
49 else:
50 data = zlib.compress(serialized)
Patrik Höglund0569a122020-03-13 12:26:42 +010051
Mirko Bonadei8cc66952020-10-30 10:13:45 +010052 print 'Sending %d bytes to %s.' % (len(data), url + '/add_histograms')
Patrik Höglund0569a122020-03-13 12:26:42 +010053
Mirko Bonadei8cc66952020-10-30 10:13:45 +010054 http = httplib2.Http()
55 response, content = http.request(url + '/add_histograms',
56 method='POST',
57 body=data,
58 headers=headers)
59 return response, content
Patrik Höglund0569a122020-03-13 12:26:42 +010060
61
Patrik Höglund457c8cf2020-03-13 14:43:21 +010062# TODO(https://crbug.com/1029452): HACKHACK
Patrik Höglund620bed12020-03-17 09:59:10 +010063# Remove once we have doubles in the proto and handle -infinity correctly.
Patrik Höglunda89ad612020-03-13 16:08:08 +010064def _ApplyHacks(dicts):
Mirko Bonadei8cc66952020-10-30 10:13:45 +010065 for d in dicts:
66 if 'running' in d:
Patrik Höglund457c8cf2020-03-13 14:43:21 +010067
Mirko Bonadei8cc66952020-10-30 10:13:45 +010068 def _NoInf(value):
69 if value == float('inf'):
70 return histogram.JS_MAX_VALUE
71 if value == float('-inf'):
72 return -histogram.JS_MAX_VALUE
73 return value
74
75 d['running'] = [_NoInf(value) for value in d['running']]
76
77 return dicts
Patrik Höglund457c8cf2020-03-13 14:43:21 +010078
79
Patrik Höglund0569a122020-03-13 12:26:42 +010080def _LoadHistogramSetFromProto(options):
Mirko Bonadei8cc66952020-10-30 10:13:45 +010081 hs = histogram_set.HistogramSet()
82 with options.input_results_file as f:
83 hs.ImportProto(f.read())
Patrik Höglund0569a122020-03-13 12:26:42 +010084
Mirko Bonadei8cc66952020-10-30 10:13:45 +010085 return hs
Patrik Höglund0569a122020-03-13 12:26:42 +010086
87
88def _AddBuildInfo(histograms, options):
Mirko Bonadei8cc66952020-10-30 10:13:45 +010089 common_diagnostics = {
90 reserved_infos.MASTERS: options.perf_dashboard_machine_group,
91 reserved_infos.BOTS: options.bot,
92 reserved_infos.POINT_ID: options.commit_position,
93 reserved_infos.BENCHMARKS: options.test_suite,
94 reserved_infos.WEBRTC_REVISIONS: str(options.webrtc_git_hash),
95 reserved_infos.BUILD_URLS: options.build_page_url,
96 }
Patrik Höglund0569a122020-03-13 12:26:42 +010097
Mirko Bonadei8cc66952020-10-30 10:13:45 +010098 for k, v in common_diagnostics.items():
99 histograms.AddSharedDiagnosticToAllHistograms(
100 k.name, generic_set.GenericSet([v]))
Patrik Höglund0569a122020-03-13 12:26:42 +0100101
102
103def _DumpOutput(histograms, output_file):
Mirko Bonadei8cc66952020-10-30 10:13:45 +0100104 with output_file:
105 json.dump(_ApplyHacks(histograms.AsDicts()), output_file, indent=4)
Patrik Höglund0569a122020-03-13 12:26:42 +0100106
107
Patrik Höglund0569a122020-03-13 12:26:42 +0100108def UploadToDashboard(options):
Mirko Bonadei8cc66952020-10-30 10:13:45 +0100109 histograms = _LoadHistogramSetFromProto(options)
110 _AddBuildInfo(histograms, options)
Patrik Höglund0569a122020-03-13 12:26:42 +0100111
Mirko Bonadei8cc66952020-10-30 10:13:45 +0100112 if options.output_json_file:
113 _DumpOutput(histograms, options.output_json_file)
Patrik Höglund0569a122020-03-13 12:26:42 +0100114
Mirko Bonadei8cc66952020-10-30 10:13:45 +0100115 oauth_token = _GenerateOauthToken()
116 response, content = _SendHistogramSet(options.dashboard_url, histograms,
117 oauth_token)
Patrik Höglund0569a122020-03-13 12:26:42 +0100118
Mirko Bonadei8cc66952020-10-30 10:13:45 +0100119 if response.status == 200:
120 print 'Received 200 from dashboard.'
121 return 0
122 else:
123 print('Upload failed with %d: %s\n\n%s' %
124 (response.status, response.reason, content))
125 return 1