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 5import collections 6import itertools 7import json 8 9from telemetry.internal.results import output_formatter 10from telemetry.value import trace 11 12def ResultsAsChartDict(benchmark_metadata, page_specific_values, 13 summary_values): 14 """Produces a dict for serialization to Chart JSON format from raw values. 15 16 Chart JSON is a transformation of the basic Telemetry JSON format that 17 removes the page map, summarizes the raw values, and organizes the results 18 by chart and trace name. This function takes the key pieces of data needed to 19 perform this transformation (namely, lists of values and a benchmark metadata 20 object) and processes them into a dict which can be serialized using the json 21 module. 22 23 Design doc for schema: http://goo.gl/kOtf1Y 24 25 Args: 26 page_specific_values: list of page-specific values 27 summary_values: list of summary values 28 benchmark_metadata: a benchmark.BenchmarkMetadata object 29 30 Returns: 31 A Chart JSON dict corresponding to the given data. 32 """ 33 values = itertools.chain( 34 output_formatter.SummarizePageSpecificValues(page_specific_values), 35 summary_values) 36 charts = collections.defaultdict(dict) 37 38 for value in values: 39 if value.page: 40 chart_name, trace_name = (value.GetChartAndTraceNameForPerPageResult()) 41 else: 42 chart_name, trace_name = ( 43 value.GetChartAndTraceNameForComputedSummaryResult(None)) 44 if chart_name == trace_name: 45 trace_name = 'summary' 46 47 # Dashboard handles the chart_name of trace values specially: it 48 # strips out the field with chart_name 'trace'. Hence in case trace 49 # value has tir_label, we preserve the chart_name. 50 # For relevant section code of dashboard code that handles this, see: 51 # https://github.com/catapult-project/catapult/blob/25e660b/dashboard/dashboard/add_point.py#L199#L216 52 if value.tir_label and not isinstance(value, trace.TraceValue): 53 chart_name = value.tir_label + '@@' + chart_name 54 55 # This intentionally overwrites the trace if it already exists because this 56 # is expected of output from the buildbots currently. 57 # See: crbug.com/413393 58 charts[chart_name][trace_name] = value.AsDict() 59 60 result_dict = { 61 'format_version': '0.1', 62 'next_version': '0.2', 63 # TODO(sullivan): benchmark_name, benchmark_description, and 64 # trace_rerun_options should be removed when incrementing format_version 65 # to 0.1. 66 'benchmark_name': benchmark_metadata.name, 67 'benchmark_description': benchmark_metadata.description, 68 'trace_rerun_options': benchmark_metadata.rerun_options, 69 'benchmark_metadata': benchmark_metadata.AsDict(), 70 'charts': charts, 71 # Need to add this in for compatibility with disabled chartjson results. 72 'enabled': True 73 } 74 75 return result_dict 76 77 78def DisabledResultsDict(benchmark_name): 79 """Produces a dict for serialization to Chart JSON when a benchmark is 80 disabled. 81 82 Args: 83 benchmark_name: name of the disabled benchmark 84 85 Returns: 86 A Chart JSON dict corresponding to a disabled benchmark. 87 """ 88 result_dict = { 89 'benchmark_name': benchmark_name, 90 'enabled': False 91 } 92 93 return result_dict 94 95 96# TODO(eakuefner): Transition this to translate Telemetry JSON. 97class ChartJsonOutputFormatter(output_formatter.OutputFormatter): 98 def __init__(self, output_stream, benchmark_metadata): 99 super(ChartJsonOutputFormatter, self).__init__(output_stream) 100 self._benchmark_metadata = benchmark_metadata 101 102 def FormatDisabled(self): 103 self._Dump(DisabledResultsDict(self._benchmark_metadata.name)) 104 105 def Format(self, page_test_results): 106 self._Dump(ResultsAsChartDict( 107 self._benchmark_metadata, 108 page_test_results.all_page_specific_values, 109 page_test_results.all_summary_values)) 110 111 def _Dump(self, results): 112 json.dump(results, self.output_stream, indent=2, 113 separators=(',', ': ')) 114 self.output_stream.write('\n') 115