mojo_benchmark: improve recording the chart data for perf dashboard.

This patch:
 - adds the neccessary metadata to `chart_data` being recorded
 - records individual `chart_data` for individual benchmarks (so that
   all measurements won't be tracked on one collective chart)
 - fixes an import error introduced in
   64736fae560422778d97e5e747458e34697cd24e

R=etiennej@chromium.org

Review URL: https://codereview.chromium.org/1412113003 .

Cr-Mirrored-From: https://github.com/domokit/mojo
Cr-Mirrored-Commit: 7615d79003f86ad1958e4a0c2d9a613d01a50569
diff --git a/devtoolslib/perf_dashboard.py b/devtoolslib/perf_dashboard.py
index aa11ff6..74eb8ca 100644
--- a/devtoolslib/perf_dashboard.py
+++ b/devtoolslib/perf_dashboard.py
@@ -13,14 +13,16 @@
 import json
 from collections import defaultdict
 
+
 class ChartDataRecorder(object):
   """Allows one to record measurement values one by one and then generate the
   JSON string that represents them in the 'chart_data' format expected by the
   performance dashboard.
   """
 
-  def __init__(self):
+  def __init__(self, benchmark_name):
     self.charts = defaultdict(list)
+    self.benchmark_name = benchmark_name
 
   def record_scalar(self, chart_name, value_name, units, value):
     """Records a single measurement value of a scalar type."""
@@ -31,5 +33,11 @@
         'value': value})
 
   def get_json(self):
-    """Returns the JSON string representing the recorded chart data."""
-    return json.dumps(self.charts)
+    """Returns the JSON string representing the recorded chart data, wrapping
+    it with the required meta data."""
+    chart_data = {
+        'format_version': '1.0',
+        'benchmark_name': self.benchmark_name,
+        'charts': self.charts
+    }
+    return json.dumps(chart_data)
diff --git a/devtoolslib/perf_dashboard_unittest.py b/devtoolslib/perf_dashboard_unittest.py
index 61809c3..b9c3b17 100644
--- a/devtoolslib/perf_dashboard_unittest.py
+++ b/devtoolslib/perf_dashboard_unittest.py
@@ -17,52 +17,64 @@
 
 from devtoolslib.perf_dashboard import ChartDataRecorder
 
+
 class ChartDataRecorderTest(unittest.TestCase):
   """Tests the chart data recorder."""
 
   def test_empty(self):
     """Tests chart data with no charts."""
-    recorder = ChartDataRecorder()
+    recorder = ChartDataRecorder('benchmark')
     result = json.loads(recorder.get_json())
-    self.assertEquals(0, len(result))
+    self.assertEquals({
+        'format_version': '1.0',
+        'benchmark_name': 'benchmark',
+        'charts': {}}, result)
 
   def test_one_chart(self):
     """Tests chart data with two samples in one chart."""
-    recorder = ChartDataRecorder()
+    recorder = ChartDataRecorder('benchmark')
     recorder.record_scalar('chart', 'val1', 'ms', 1)
     recorder.record_scalar('chart', 'val2', 'ms', 2)
 
     result = json.loads(recorder.get_json())
-    self.assertEquals(1, len(result))
-    self.assertEquals(2, len(result['chart']))
+    self.assertEquals('1.0', result['format_version'])
+    self.assertEquals('benchmark', result['benchmark_name'])
+
+    charts = result['charts']
+    self.assertEquals(1, len(charts))
+    self.assertEquals(2, len(charts['chart']))
     self.assertEquals({
         'type': 'scalar',
         'name': 'val1',
         'units': 'ms',
-        'value': 1}, result['chart'][0])
+        'value': 1}, charts['chart'][0])
     self.assertEquals({
         'type': 'scalar',
         'name': 'val2',
         'units': 'ms',
-        'value': 2}, result['chart'][1])
+        'value': 2}, charts['chart'][1])
 
   def test_two_charts(self):
     """Tests chart data with two samples over two charts."""
-    recorder = ChartDataRecorder()
+    recorder = ChartDataRecorder('benchmark')
     recorder.record_scalar('chart1', 'val1', 'ms', 1)
     recorder.record_scalar('chart2', 'val2', 'ms', 2)
 
     result = json.loads(recorder.get_json())
-    self.assertEquals(2, len(result))
-    self.assertEquals(1, len(result['chart1']))
+    self.assertEquals('1.0', result['format_version'])
+    self.assertEquals('benchmark', result['benchmark_name'])
+
+    charts = result['charts']
+    self.assertEquals(2, len(charts))
+    self.assertEquals(1, len(charts['chart1']))
     self.assertEquals({
         'type': 'scalar',
         'name': 'val1',
         'units': 'ms',
-        'value': 1}, result['chart1'][0])
-    self.assertEquals(1, len(result['chart2']))
+        'value': 1}, charts['chart1'][0])
+    self.assertEquals(1, len(charts['chart2']))
     self.assertEquals({
         'type': 'scalar',
         'name': 'val2',
         'units': 'ms',
-        'value': 2}, result['chart2'][0])
+        'value': 2}, charts['chart2'][0])
diff --git a/mojo_benchmark b/mojo_benchmark
index 5ffdbe1..8413490 100755
--- a/mojo_benchmark
+++ b/mojo_benchmark
@@ -14,7 +14,7 @@
 
 from devtoolslib import shell_arguments
 from devtoolslib import shell_config
-from devtoolslib import performance_dashboard
+from devtoolslib import perf_dashboard
 
 
 _DESCRIPTION = """Runner for Mojo application benchmarks.
@@ -195,10 +195,6 @@
   benchmark_list_params = {"target_os": target_os}
   exec script_args.benchmark_list_file in benchmark_list_params
 
-  chart_data_recorder = None
-  if script_args.chart_data_output_file:
-    chart_data_recorder = performance_dashboard.ChartDataRecorder()
-
   exit_code = 0
   for benchmark_spec in benchmark_list_params['benchmarks']:
     for variant_spec in _generate_benchmark_variants(benchmark_spec):
@@ -207,6 +203,10 @@
       duration = variant_spec['duration']
       shell_args = variant_spec.get('shell-args', []) + common_shell_args
       measurements = variant_spec['measurements']
+
+      chart_data_recorder = None
+      if script_args.chart_data_output_file:
+        chart_data_recorder = perf_dashboard.ChartDataRecorder(name)
       benchmark_succeeded, benchmark_error, output = _run_benchmark(
           shell, shell_args, name, app, duration, measurements,
           script_args.verbose, script_args.android,
@@ -243,8 +243,9 @@
         print '-' * 72
         exit_code = 1
 
-  if script_args.chart_data_output_file:
-    script_args.chart_data_output_file.write(chart_data_recorder.get_json())
+      if script_args.chart_data_output_file:
+        script_args.chart_data_output_file.write(chart_data_recorder.get_json())
+        script_args.chart_data_output_file.write('\n')
 
   return exit_code