1# Copyright 2013 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import datetime 6import json 7import logging 8import os 9import re 10import sys 11 12from telemetry.core import util 13from telemetry.page import buildbot_page_measurement_results 14 15# Get build/util scripts into our path. 16sys.path.append(os.path.abspath(os.path.join( 17 util.GetChromiumSrcDir(), 'build', 'util'))) 18import lastchange # pylint: disable=F0401 19 20 21_TEMPLATE_HTML_PATH = os.path.join( 22 util.GetTelemetryDir(), 'support', 'html_output', 'results-template.html') 23_PLUGINS = [('third_party', 'flot', 'jquery.flot.min.js'), 24 ('third_party', 'WebKit', 'PerformanceTests', 'resources', 25 'jquery.tablesorter.min.js'), 26 ('third_party', 'WebKit', 'PerformanceTests', 'resources', 27 'statistics.js')] 28_UNIT_JSON = ('tools', 'perf', 'unit-info.json') 29 30 31class HtmlPageMeasurementResults( 32 buildbot_page_measurement_results.BuildbotPageMeasurementResults): 33 def __init__(self, output_stream, test_name, reset_results, browser_type, 34 trace_tag=''): 35 super(HtmlPageMeasurementResults, self).__init__(trace_tag) 36 37 self._output_stream = output_stream 38 self._reset_results = reset_results 39 self._test_name = test_name 40 self._result_json = { 41 'buildTime': self._GetBuildTime(), 42 'revision': self._GetRevision(), 43 'platform': browser_type, 44 'tests': {} 45 } 46 47 def _GetBuildTime(self): 48 def _DatetimeInEs5CompatibleFormat(dt): 49 return dt.strftime('%Y-%m-%dT%H:%M:%S.%f') 50 return _DatetimeInEs5CompatibleFormat(datetime.datetime.utcnow()) 51 52 def _GetRevision(self): 53 return lastchange.FetchVersionInfo(None).revision 54 55 def _GetHtmlTemplate(self): 56 return open(_TEMPLATE_HTML_PATH, 'r').read() 57 58 def _GetPlugins(self): 59 plugins = '' 60 for p in _PLUGINS: 61 plugins += open(os.path.join(util.GetChromiumSrcDir(), *p), 'r').read() 62 return plugins 63 64 def _GetUnitJson(self): 65 return open(os.path.join(util.GetChromiumSrcDir(), *_UNIT_JSON), 'r').read() 66 67 def _GetResultsJson(self): 68 results_html = self._output_stream.read() 69 if self._reset_results or not results_html: 70 return [] 71 m = re.search( 72 '^<script id="results-json" type="application/json">(.*?)</script>$', 73 results_html, re.MULTILINE | re.DOTALL) 74 if not m: 75 logging.warn('Failed to extract previous results from HTML output') 76 return [] 77 return json.loads(m.group(1)) 78 79 def _SaveResults(self, results): 80 self._output_stream.seek(0) 81 self._output_stream.write(results) 82 self._output_stream.truncate() 83 84 def _PrintPerfResult(self, measurement, trace, values, units, 85 result_type='default'): 86 super(HtmlPageMeasurementResults, self)._PrintPerfResult( 87 measurement, trace, values, units, result_type) 88 89 metric_name = measurement 90 if trace != measurement: 91 metric_name += '.' + trace 92 self._result_json['tests'].setdefault(self._test_name, {}) 93 self._result_json['tests'][self._test_name].setdefault('metrics', {}) 94 self._result_json['tests'][self._test_name]['metrics'][metric_name] = { 95 'current': values, 96 'units': units, 97 'important': result_type == 'default' 98 } 99 100 def PrintSummary(self): 101 super(HtmlPageMeasurementResults, self).PrintSummary() 102 103 json_results = self._GetResultsJson() 104 json_results.append(self._result_json) 105 html = self._GetHtmlTemplate() 106 html = html.replace('%json_results%', json.dumps(json_results)) 107 html = html.replace('%json_units%', self._GetUnitJson()) 108 html = html.replace('%plugins%', self._GetPlugins()) 109 self._SaveResults(html) 110 111 print 112 print 'View result at file://%s' % os.path.abspath(self._output_stream.name) 113