Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(203)

Side by Side Diff: tools/telemetry/telemetry/results/html_output_formatter.py

Issue 1118593002: [Telemetry] Change HTMLOutputFormatter to be based on chart JSON (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Explicitly ignore TraceValues in chart JSON translator Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import datetime 5 import datetime
6 import json 6 import json
7 import logging 7 import logging
8 import os 8 import os
9 import re 9 import re
10 10
11 from telemetry import value as value_module
11 from telemetry.core import util 12 from telemetry.core import util
12 from telemetry.results import buildbot_output_formatter 13 from telemetry.results import chart_json_output_formatter
14 from telemetry.results import output_formatter
13 from telemetry.util import cloud_storage 15 from telemetry.util import cloud_storage
14 16
15 util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'util') 17 util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'util')
16 import lastchange # pylint: disable=F0401 18 import lastchange # pylint: disable=F0401
17 19
18 20
19 _TEMPLATE_HTML_PATH = os.path.join( 21 _TEMPLATE_HTML_PATH = os.path.join(
20 util.GetTelemetryDir(), 'support', 'html_output', 'results-template.html') 22 util.GetTelemetryDir(), 'support', 'html_output', 'results-template.html')
21 _PLUGINS = [('third_party', 'flot', 'jquery.flot.min.js'), 23 _PLUGINS = [('third_party', 'flot', 'jquery.flot.min.js'),
22 ('third_party', 'WebKit', 'PerformanceTests', 'resources', 24 ('third_party', 'WebKit', 'PerformanceTests', 'resources',
23 'jquery.tablesorter.min.js'), 25 'jquery.tablesorter.min.js'),
24 ('third_party', 'WebKit', 'PerformanceTests', 'resources', 26 ('third_party', 'WebKit', 'PerformanceTests', 'resources',
25 'statistics.js')] 27 'statistics.js')]
26 _UNIT_JSON = ('tools', 'perf', 'unit-info.json') 28 _UNIT_JSON = ('tools', 'perf', 'unit-info.json')
27 29
28 30
29 # TODO(chrishenry): This should not really extend BuildbotOutputFormatter. 31 # TODO(eakuefner): rewrite template to use Telemetry JSON directly
30 # Leaving as-is now since we are going to move HtmlOutputFormatter to be 32 class HtmlOutputFormatter(output_formatter.OutputFormatter):
31 # based on JSON anyway.
32 class HtmlOutputFormatter(buildbot_output_formatter.BuildbotOutputFormatter):
33 def __init__(self, output_stream, metadata, reset_results, upload_results, 33 def __init__(self, output_stream, metadata, reset_results, upload_results,
34 browser_type, results_label=None, trace_tag=''): 34 browser_type, results_label=None):
35 # Pass output_stream=None so that we blow up if 35 super(HtmlOutputFormatter, self).__init__(output_stream)
36 # BuildbotOutputFormatter ever use the output_stream.
37 super(HtmlOutputFormatter, self).__init__(None, trace_tag)
38 self._metadata = metadata 36 self._metadata = metadata
39 self._reset_results = reset_results 37 self._reset_results = reset_results
40 self._upload_results = upload_results 38 self._upload_results = upload_results
41 self._html_output_stream = output_stream
42 self._existing_results = self._ReadExistingResults(output_stream) 39 self._existing_results = self._ReadExistingResults(output_stream)
43 self._result = { 40 self._result = {
44 'buildTime': self._GetBuildTime(), 41 'buildTime': self._GetBuildTime(),
45 'revision': self._GetRevision(), 42 'revision': self._GetRevision(),
46 'label': results_label, 43 'label': results_label,
47 'platform': browser_type, 44 'platform': browser_type,
48 'tests': {} 45 'tests': {}
49 } 46 }
50 47
51 def _GetBuildTime(self): 48 def _GetBuildTime(self):
(...skipping 25 matching lines...) Expand all
77 return [] 74 return []
78 m = re.search( 75 m = re.search(
79 '^<script id="results-json" type="application/json">(.*?)</script>$', 76 '^<script id="results-json" type="application/json">(.*?)</script>$',
80 results_html, re.MULTILINE | re.DOTALL) 77 results_html, re.MULTILINE | re.DOTALL)
81 if not m: 78 if not m:
82 logging.warn('Failed to extract previous results from HTML output') 79 logging.warn('Failed to extract previous results from HTML output')
83 return [] 80 return []
84 return json.loads(m.group(1))[:512] 81 return json.loads(m.group(1))[:512]
85 82
86 def _SaveResults(self, results): 83 def _SaveResults(self, results):
87 self._html_output_stream.seek(0) 84 self._output_stream.seek(0)
88 self._html_output_stream.write(results) 85 self._output_stream.write(results)
89 self._html_output_stream.truncate() 86 self._output_stream.truncate()
90 87
91 def _PrintPerfResult(self, measurement, trace, values, units, 88 def _PrintPerfResult(self, measurement, trace, values, units,
92 result_type='default'): 89 result_type='default'):
93 metric_name = measurement 90 metric_name = measurement
94 if trace != measurement: 91 if trace != measurement:
95 metric_name += '.' + trace 92 metric_name += '.' + trace
96 self._result['tests'].setdefault(self._test_name, {}) 93 self._result['tests'].setdefault(self._test_name, {})
97 self._result['tests'][self._test_name].setdefault('metrics', {}) 94 self._result['tests'][self._test_name].setdefault('metrics', {})
98 self._result['tests'][self._test_name]['metrics'][metric_name] = { 95 self._result['tests'][self._test_name]['metrics'][metric_name] = {
99 'current': values, 96 'current': values,
100 'units': units, 97 'units': units,
101 'important': result_type == 'default' 98 'important': result_type == 'default'
102 } 99 }
103 100
101 def _TranslateChartJson(self, chart_json_dict):
102 dummy_dict = dict()
103
104 for chart_name, traces in chart_json_dict['charts'].iteritems():
105 for trace_name, value_dict in traces.iteritems():
106 # TODO(eakuefner): refactor summarization so we don't have to jump
107 # through hoops like this.
108 if 'page_id' in value_dict:
109 del value_dict['page_id']
110 result_type = 'nondefault'
111 else:
112 result_type = 'default'
113
114 # Note: we explicitly ignore TraceValues because Buildbot did.
115 if value_dict['type'] == 'trace':
116 continue
117 value = value_module.Value.FromDict(value_dict, dummy_dict)
118
119 perf_value = value.GetBuildbotValue()
120
121 if trace_name == 'summary':
122 trace_name = chart_name
123
124 self._PrintPerfResult(chart_name, trace_name, perf_value,
125 value.units, result_type)
126
104 @property 127 @property
105 def _test_name(self): 128 def _test_name(self):
106 return self._metadata.name 129 return self._metadata.name
107 130
108 def GetResults(self): 131 def GetResults(self):
109 return self._result 132 return self._result
110 133
111 def GetCombinedResults(self): 134 def GetCombinedResults(self):
112 all_results = list(self._existing_results) 135 all_results = list(self._existing_results)
113 all_results.append(self.GetResults()) 136 all_results.append(self.GetResults())
114 return all_results 137 return all_results
115 138
116 def Format(self, page_test_results): 139 def Format(self, page_test_results):
117 super(HtmlOutputFormatter, self).Format(page_test_results) 140 chart_json_dict = chart_json_output_formatter.ResultsAsChartDict(
141 self._metadata, page_test_results.all_page_specific_values,
142 page_test_results.all_summary_values)
143
144 self._TranslateChartJson(chart_json_dict)
145 self._PrintPerfResult('telemetry_page_measurement_results', 'num_failed',
146 [len(page_test_results.failures)], 'count',
147 'unimportant')
118 148
119 html = self._GetHtmlTemplate() 149 html = self._GetHtmlTemplate()
120 html = html.replace('%json_results%', json.dumps(self.GetCombinedResults())) 150 html = html.replace('%json_results%', json.dumps(self.GetCombinedResults()))
121 html = html.replace('%json_units%', self._GetUnitJson()) 151 html = html.replace('%json_units%', self._GetUnitJson())
122 html = html.replace('%plugins%', self._GetPlugins()) 152 html = html.replace('%plugins%', self._GetPlugins())
123 self._SaveResults(html) 153 self._SaveResults(html)
124 154
125 if self._upload_results: 155 if self._upload_results:
126 file_path = os.path.abspath(self._html_output_stream.name) 156 file_path = os.path.abspath(self._output_stream.name)
127 file_name = 'html-results/results-%s' % datetime.datetime.now().strftime( 157 file_name = 'html-results/results-%s' % datetime.datetime.now().strftime(
128 '%Y-%m-%d_%H-%M-%S') 158 '%Y-%m-%d_%H-%M-%S')
129 try: 159 try:
130 cloud_storage.Insert(cloud_storage.PUBLIC_BUCKET, file_name, file_path) 160 cloud_storage.Insert(cloud_storage.PUBLIC_BUCKET, file_name, file_path)
131 print 161 print
132 print ('View online at ' 162 print ('View online at '
133 'http://storage.googleapis.com/chromium-telemetry/%s' 163 'http://storage.googleapis.com/chromium-telemetry/%s'
134 % file_name) 164 % file_name)
135 except cloud_storage.PermissionError as e: 165 except cloud_storage.PermissionError as e:
136 logging.error('Cannot upload profiling files to cloud storage due to ' 166 logging.error('Cannot upload profiling files to cloud storage due to '
137 ' permission error: %s' % e.message) 167 ' permission error: %s' % e.message)
138 print 168 print
139 print 'View result at file://%s' % os.path.abspath( 169 print 'View result at file://%s' % os.path.abspath(
140 self._html_output_stream.name) 170 self._output_stream.name)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698