blob: 4d5ff88f6564614b13419b93ac3ed7222e42686c [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
10
11import httplib2
12import json
13import subprocess
14import zlib
15
16from tracing.value import histogram_set
17from tracing.value.diagnostics import generic_set
18from tracing.value.diagnostics import reserved_infos
19
20
21def _GenerateOauthToken():
22 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()))
31
32
33def _SendHistogramSet(url, histograms, oauth_token):
34 """Make a HTTP POST with the given JSON to the Performance Dashboard.
35
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 """
42 headers = {'Authorization': 'Bearer %s' % oauth_token}
43
Patrik Höglunda89ad612020-03-13 16:08:08 +010044 serialized = json.dumps(_ApplyHacks(histograms.AsDicts()), indent=4)
Patrik Höglund0569a122020-03-13 12:26:42 +010045
46 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)
51
52 print 'Sending %d bytes to %s.' % (len(data), url + '/add_histograms')
53
54 http = httplib2.Http()
55 response, content = http.request(url + '/add_histograms', method='POST',
56 body=data, headers=headers)
57 return response, content
58
59
Patrik Höglund457c8cf2020-03-13 14:43:21 +010060# TODO(https://crbug.com/1029452): HACKHACK
61# Remove once we set bin bounds correctly in the proto writer.
Patrik Höglunda89ad612020-03-13 16:08:08 +010062def _ApplyHacks(dicts):
Patrik Höglund457c8cf2020-03-13 14:43:21 +010063 for d in dicts:
64 if 'name' in d:
65 d['allBins'] = [[1]]
Patrik Höglunda89ad612020-03-13 16:08:08 +010066 del d['binBoundaries']
67 d['diagnostics']['stories']['values'][0] = (
68 d['diagnostics']['stories']['values'][0].replace('/', '_'))
Patrik Höglund457c8cf2020-03-13 14:43:21 +010069
70 return dicts
71
72
Patrik Höglund0569a122020-03-13 12:26:42 +010073def _LoadHistogramSetFromProto(options):
74 hs = histogram_set.HistogramSet()
75 with options.input_results_file as f:
76 hs.ImportProto(f.read())
77
78 return hs
79
80
81def _AddBuildInfo(histograms, options):
82 common_diagnostics = {
83 reserved_infos.MASTERS: options.perf_dashboard_machine_group,
84 reserved_infos.BOTS: options.bot,
85 reserved_infos.POINT_ID: options.commit_position,
86 reserved_infos.BENCHMARKS: options.test_suite,
87 reserved_infos.WEBRTC_REVISIONS: str(options.webrtc_git_hash),
88 reserved_infos.BUILD_URLS: options.build_page_url,
89 }
90
91 for k, v in common_diagnostics.items():
92 histograms.AddSharedDiagnosticToAllHistograms(
93 k.name, generic_set.GenericSet([v]))
94
95
96def _DumpOutput(histograms, output_file):
97 with output_file:
Patrik Höglunda89ad612020-03-13 16:08:08 +010098 json.dump(_ApplyHacks(histograms.AsDicts()), output_file, indent=4)
Patrik Höglund0569a122020-03-13 12:26:42 +010099
100
101# TODO(https://crbug.com/1029452): Remove this once
102# https://chromium-review.googlesource.com/c/catapult/+/2094312 lands.
103def _HackSummaryOptions(histograms):
104 for histogram in histograms:
105 histogram.CustomizeSummaryOptions({
106 'avg': False,
107 'std': False,
108 'count': False,
109 'sum': False,
110 'min': False,
111 'max': False,
112 'nans': False,
113 })
114
115
116def UploadToDashboard(options):
117 histograms = _LoadHistogramSetFromProto(options)
118 _AddBuildInfo(histograms, options)
119 _HackSummaryOptions(histograms)
120
121 if options.output_json_file:
122 _DumpOutput(histograms, options.output_json_file)
123
124 oauth_token = _GenerateOauthToken()
125 response, content = _SendHistogramSet(
126 options.dashboard_url, histograms, oauth_token)
127
128 if response.status == 200:
129 print 'Received 200 from dashboard.'
130 return 0
131 else:
132 print('Upload failed with %d: %s\n\n%s' % (response.status, response.reason,
133 content))
134 return 1