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
3# found in the LICENSE file.
4
5from telemetry import decorators
6from telemetry.internal.results import output_formatter
7from telemetry.util import perf_tests_helper
8from telemetry import value as value_module
9from telemetry.value import summary as summary_module
10
11
12@decorators.Deprecated(2016, 2, 29, 'Chart JSON is a supported alternative. '
13                       'See https://goo.gl/8daFav .')
14class BuildbotOutputFormatter(output_formatter.OutputFormatter):
15  def __init__(self, output_stream, trace_tag=''):
16    super(BuildbotOutputFormatter, self).__init__(output_stream)
17    self._trace_tag = trace_tag
18
19  def _PrintPerfResult(self, measurement, trace, v, units,
20                       result_type='default'):
21    output = perf_tests_helper.PrintPerfResult(
22        measurement, trace, v, units, result_type, print_to_stdout=False)
23    self.output_stream.write(output + '\n')
24    self.output_stream.flush()
25
26  def Format(self, page_test_results):
27    """Print summary data in a format expected by buildbot for perf dashboards.
28
29    If any failed pages exist, only output individual page results, and do
30    not output any average data.
31    """
32    had_failures = len(page_test_results.failures) > 0
33
34    # Print out the list of unique pages.
35    perf_tests_helper.PrintPages(
36        [page.display_name for page in page_test_results.pages_that_succeeded])
37    summary = summary_module.Summary(page_test_results.all_page_specific_values)
38    for value in summary.interleaved_computed_per_page_values_and_summaries:
39      if value.page:
40        self._PrintComputedPerPageValue(value)
41      else:
42        self._PrintComputedSummaryValue(value, had_failures)
43    self._PrintOverallResults(page_test_results)
44
45  def _PrintComputedPerPageValue(self, value):
46    # We dont print per-page-values when there is a trace tag.
47    if self._trace_tag:
48      return
49
50    # Actually print the result.
51    buildbot_value = value.GetBuildbotValue()
52    buildbot_data_type = value.GetBuildbotDataType(
53        output_context=value_module.PER_PAGE_RESULT_OUTPUT_CONTEXT)
54    if buildbot_value is None or buildbot_data_type is None:
55      return
56
57    buildbot_measurement_name, buildbot_trace_name = (
58        value.GetChartAndTraceNameForPerPageResult())
59    if value.tir_label:
60      buildbot_measurement_name = '%s-%s' % (value.tir_label,
61                                             buildbot_measurement_name)
62    self._PrintPerfResult(buildbot_measurement_name,
63                          buildbot_trace_name,
64                          buildbot_value, value.units, buildbot_data_type)
65
66  def _PrintComputedSummaryValue(self, value, had_failures):
67    # If there were any page errors, we typically will print nothing.
68    #
69    # Note: this branch is structured less-densely to improve legibility.
70    if had_failures:
71      return
72
73    buildbot_value = value.GetBuildbotValue()
74    buildbot_data_type = value.GetBuildbotDataType(
75        output_context=value_module.COMPUTED_PER_PAGE_SUMMARY_OUTPUT_CONTEXT)
76    if buildbot_value is None or buildbot_data_type is None:
77      return
78
79    buildbot_measurement_name, buildbot_trace_name = (
80        value.GetChartAndTraceNameForComputedSummaryResult(
81            self._trace_tag))
82    if value.tir_label:
83      buildbot_measurement_name = '%s-%s' % (value.tir_label,
84                                             buildbot_measurement_name)
85      buildbot_trace_name = '%s-%s' % (value.tir_label,
86                                       buildbot_trace_name)
87    self._PrintPerfResult(buildbot_measurement_name,
88                          buildbot_trace_name,
89                          buildbot_value, value.units, buildbot_data_type)
90
91  def _PrintOverallResults(self, page_test_results):
92    # If there were no failed pages, output the overall results (results not
93    # associated with a page).
94    had_failures = len(page_test_results.failures) > 0
95    if not had_failures:
96      for value in page_test_results.all_summary_values:
97        buildbot_value = value.GetBuildbotValue()
98        buildbot_data_type = value.GetBuildbotDataType(
99            output_context=value_module.SUMMARY_RESULT_OUTPUT_CONTEXT)
100        buildbot_measurement_name, buildbot_trace_name = (
101            value.GetChartAndTraceNameForComputedSummaryResult(
102                self._trace_tag))
103        self._PrintPerfResult(
104            buildbot_measurement_name,
105            buildbot_trace_name,
106            buildbot_value,
107            value.units,
108            buildbot_data_type)
109
110    # Print the number of failed and errored pages.
111    self._PrintPerfResult('telemetry_page_measurement_results', 'num_failed',
112                          [len(page_test_results.failures)], 'count',
113                          'unimportant')
114
115    # TODO(chrishenry): Remove this in a separate patch to reduce the risk
116    # of rolling back due to buildbot breakage.
117    # Also fix src/tools/bisect-perf-regression_test.py when this is
118    # removed.
119    self._PrintPerfResult('telemetry_page_measurement_results', 'num_errored',
120                          [0], 'count', 'unimportant')
121