blob: 20af6a491a251e81a2e677849ea1fb6f217d385e [file] [log] [blame]
#! /usr/bin/env python
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# pylint: disable=R0201
"""Log parsing for telemetry tests.
The TelemetryResultsProcessor loads and contains results that were output in
JSON format from Telemetry. It can be used as a replacement for the classes in
the performance_log_processor module.
"""
import json
import logging
import os
from slave.performance_log_processor import _FormatHumanReadable
class TelemetryResultsProcessor(object):
def __init__(self, filename, is_ref, cleanup_parent_dir):
self._chart_filename = filename
self._is_reference_build = is_ref
self._cleanup_parent_dir = cleanup_parent_dir
def ChartJson(self):
try:
with open(self._chart_filename) as f:
return json.load(f)
except (IOError, ValueError):
logging.error('Error reading telemetry results from %s',
self._chart_filename)
logging.error('This usually means that telemetry did not run, so it could'
' not generate the file. Please check the device running the test.')
return None
def Cleanup(self):
try:
os.remove(self._chart_filename)
except OSError:
logging.error('Unable to remove telemetry output file %s',
self._chart_filename)
if self._cleanup_parent_dir:
try:
os.rmdir(os.path.dirname(self._chart_filename))
except OSError:
logging.error('Unable to remove telemetry output dir %s',
os.path.dirname(self._chart_filename))
def IsChartJson(self):
"""This is the new telemetry --chartjson output format."""
return True
def IsHistogramSet(self):
"""This is not the newer HistogramSet format that replaces ChartJSON."""
return False
def IsReferenceBuild(self):
return self._is_reference_build
def ProcessLine(self, line):
pass
def FailedTests(self):
return []
def MemoryToolReportHashes(self): # pylint: disable=R0201
return []
def ParsingErrors(self): # pylint: disable=R0201
return []
def PerformanceSummary(self):
"""Writes the waterfall display text.
The waterfall contains lines for each important trace, in the form
tracename: value< (refvalue)>
"""
if self._is_reference_build:
return []
chartjson_data = self.ChartJson()
if not chartjson_data:
return []
charts = chartjson_data.get('charts')
if not charts:
return []
def _summary_to_string(chart_name, chart_values):
summary = chart_values.get('summary')
if not summary:
return None
important = summary.get('important')
if not important:
return None
value_type = summary.get('type')
if value_type == 'list_of_scalar_values':
values = summary.get('values')
if not values or None in values:
return '%s: %s' % (chart_name, 'NaN')
else:
mean = sum(values) / float(len(values))
return '%s: %s' % (chart_name, _FormatHumanReadable(mean))
elif value_type == 'scalar':
value = summary.get('value')
if value is None:
return '%s: %s' % (chart_name, 'NaN')
else:
return '%s: %s' % (chart_name, _FormatHumanReadable(value))
return None
gen = (_summary_to_string(chart_name, chart_values)
for chart_name, chart_values in sorted(charts.iteritems()))
return [i for i in gen if i]