Commit 7fda4612 authored by Mikhail Khokhlov's avatar Mikhail Khokhlov Committed by Commit Bot

[tools/perf] Implement traces aggregation in Results Processor

Bug: 981349
Change-Id: I1a47afea1dedcd352a0d6999f7119246b74b737f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1849855
Commit-Queue: Mikhail Khokhlov <khokhlov@google.com>
Reviewed-by: default avatarJuan Antonio Navarro Pérez <perezju@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704705}
parent 4607d229
......@@ -20,6 +20,7 @@ from core.results_processor import compute_metrics
from core.results_processor import formatters
from core.results_processor import util
from tracing.trace_data import trace_data
from tracing.value.diagnostics import generic_set
from tracing.value.diagnostics import reserved_infos
from tracing.value import histogram_set
......@@ -46,7 +47,7 @@ def ProcessResults(options):
intermediate_results = _LoadIntermediateResults(
os.path.join(options.intermediate_dir, TELEMETRY_RESULTS))
_AggregateTraces(intermediate_results)
AggregateTraces(intermediate_results)
UploadArtifacts(
intermediate_results, options.upload_bucket, options.results_label)
......@@ -99,7 +100,7 @@ def _LoadIntermediateResults(intermediate_file):
return results
def _AggregateTraces(intermediate_results):
def AggregateTraces(intermediate_results):
"""Replace individual traces with an aggregate one for each test result.
For each test run with traces, generates an aggregate HTML trace. Removes
......@@ -109,10 +110,16 @@ def _AggregateTraces(intermediate_results):
artifacts = result.get('outputArtifacts', {})
traces = [name for name in artifacts if name.startswith('trace/')]
if len(traces) > 0:
# For now, the html trace is generated by Telemetry, so it should be there
# already. All we need to do is remove individual traces from the dict.
# TODO(crbug.com/981349): replace this with actual aggregation code.
assert compute_metrics.HTML_TRACE_NAME in artifacts
if compute_metrics.HTML_TRACE_NAME not in artifacts:
trace_files = [artifacts[name]['filePath'] for name in traces]
html_path = os.path.join(
os.path.dirname(os.path.commonprefix(trace_files)),
compute_metrics.HTML_TRACE_NAME)
trace_data.SerializeAsHtml(trace_files, html_path)
artifacts[compute_metrics.HTML_TRACE_NAME] = {
'filePath': html_path,
'contentType': 'text/html',
}
for trace in traces:
del artifacts[trace]
......
......@@ -24,6 +24,7 @@ from core.results_processor import compute_metrics
from core.results_processor import processor
from core.results_processor import testing
from tracing.value.diagnostics import generic_set
from tracing.value import histogram
from tracing.value import histogram_set
from tracing_build import render_histograms_viewer
......@@ -268,12 +269,45 @@ class ResultsProcessorIntegrationTests(unittest.TestCase):
out_histograms = histogram_set.HistogramSet()
out_histograms.ImportDicts(results)
self.assertEqual(len(out_histograms), 4)
self.assertIsNotNone(out_histograms.GetHistogramNamed('foo'))
diag_values = [list(v) for v in out_histograms.shared_diagnostics]
self.assertEqual(len(diag_values), 1)
self.assertIn(['gs://trace.html'], diag_values)
# sampleMetric records a histogram with the name 'foo'.
hist = out_histograms.GetHistogramNamed('foo')
self.assertIsNotNone(hist)
self.assertEqual(hist.diagnostics['traceUrls'],
generic_set.GenericSet(['gs://trace.html']))
def testHistogramsOutputNoAggregatedTrace(self):
json_trace = os.path.join(self.output_dir, 'trace.json')
with open(json_trace, 'w') as f:
json.dump({'traceEvents': []}, f)
self.SerializeIntermediateResults(
test_results=[
testing.TestResult(
'benchmark/story',
output_artifacts={'trace/json': testing.Artifact(json_trace)},
tags=['tbmv2:sampleMetric'],
),
],
)
processor.main([
'--output-format', 'histograms',
'--output-dir', self.output_dir,
'--intermediate-dir', self.intermediate_dir,
])
with open(os.path.join(
self.output_dir, histograms_output.OUTPUT_FILENAME)) as f:
results = json.load(f)
out_histograms = histogram_set.HistogramSet()
out_histograms.ImportDicts(results)
# sampleMetric records a histogram with the name 'foo'.
hist = out_histograms.GetHistogramNamed('foo')
self.assertIsNotNone(hist)
self.assertIn('traceUrls', hist.diagnostics)
def testHtmlOutput(self):
hist_file = os.path.join(self.output_dir,
......
......@@ -94,3 +94,55 @@ class ResultsProcessorUnitTests(unittest.TestCase):
'src_abc_123_20191001T120000_54321/benchmark/story/trace.html',
'/trace.html'
)
def testAggregateTraces(self):
in_results = testing.IntermediateResults(
test_results=[
testing.TestResult(
'benchmark/story1',
output_artifacts={
'trace/1.json': testing.Artifact(
'/artifacts/test_run/story1/trace/1.json'),
},
),
testing.TestResult(
'benchmark/story2',
output_artifacts={
'trace/1.json': testing.Artifact(
'/artifacts/test_run/story2/trace/1.json'),
'trace/2.json': testing.Artifact(
'/artifacts/test_run/story2/trace/2.json'),
},
),
],
)
with mock.patch('tracing.trace_data.trace_data.SerializeAsHtml') as patch:
processor.AggregateTraces(in_results)
call_list = [list(call[0]) for call in patch.call_args_list]
self.assertEqual(len(call_list), 2)
for call in call_list:
call[0] = set(call[0])
self.assertIn(
[
set(['/artifacts/test_run/story1/trace/1.json']),
'/artifacts/test_run/story1/trace/trace.html',
],
call_list
)
self.assertIn(
[
set([
'/artifacts/test_run/story2/trace/1.json',
'/artifacts/test_run/story2/trace/2.json',
]),
'/artifacts/test_run/story2/trace/trace.html',
],
call_list
)
for result in in_results['testResults']:
artifacts = result['outputArtifacts']
self.assertEqual(len(artifacts), 1)
self.assertEqual(artifacts.keys()[0], 'trace.html')
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment