Chromium Code Reviews| Index: systrace/systrace/systrace_tracing_controller.py |
| diff --git a/systrace/systrace/systrace_tracing_controller.py b/systrace/systrace/systrace_tracing_controller.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..226bdeeefa95adbfddf82869f6da4759b236e781 |
| --- /dev/null |
| +++ b/systrace/systrace/systrace_tracing_controller.py |
| @@ -0,0 +1,166 @@ |
| +#!/usr/bin/env python |
| + |
| +# Copyright (c) 2016 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. |
| + |
| +'''Implementation of tracing controller for systrace. This class creates the |
| +necessary tracing agents for systrace, runs them, and outputs the results |
| +as an HTML file.''' |
| + |
| +import imp |
| +import os |
| +import json |
| + |
| +from systrace import tracing_controller |
| + |
| +# The default agent directory. |
| +DEFAULT_AGENT_DIR = 'tracing_agents' |
| + |
| + |
| +class SystraceTracingController(tracing_controller.TracingController): |
| + def __init__(self, script_dir, options, categories): |
| + """Set up the SystraceTracingController. |
| + |
| + Args: |
| + script_dir: Directory containing the trace viewer script |
| + (systrace_trace_viewer.html) |
| + options: List of command line options. |
| + categories: List of trace categories to capture. |
| + """ |
| + # Parse command line arguments and create agents |
| + self._script_dir = script_dir |
| + self._out_filename = options.output_file |
| + agents = CreateAgents(options, categories) |
| + |
| + # Error if no agents are available |
| + if not agents: |
| + dirs = DEFAULT_AGENT_DIR |
| + if options.agent_dirs: |
| + dirs += ',' + options.agent_dirs |
| + raise RuntimeError('No systrace agent is available' |
| + 'in directories |%s|.\n' % dirs) |
| + |
| + # Update trace viewer if necessary |
| + try: |
| + update_systrace_trace_viewer = __import__('update_systrace_trace_viewer') |
| + except ImportError: |
| + pass |
| + else: |
| + update_systrace_trace_viewer.update() |
|
Zhen Wang
2016/03/29 18:53:39
Pass script_dir to update_systrace_trace_viewer an
alexandermont
2016/03/30 01:04:24
Done
|
| + |
| + super(SystraceTracingController, self).__init__(agents) |
| + |
| + def SupportsExplicitClockSync(self): |
| + return False |
| + |
| + def RecordClockSyncMarker(self, sync_id, callback): |
| + raise NotImplementedError |
| + |
| + def OutputSystraceResults(self, write_json=False): |
| + """Output the results of systrace to a file. |
| + |
| + If output is necessary, then write the results of systrace to either (a) |
| + a standalone HTML file, or (b) a json file which can be read by the |
| + trace viewer. |
| + |
| + Args: |
| + json: Whether to output to a json file (if false, use HTML file) |
| + """ |
| + print 'Tracing complete, writing results' |
| + if write_json: |
| + self._WriteTraceJSON(self._all_results) |
| + else: |
| + self._WriteTraceHTML(self._all_results) |
| + |
| + def _WriteTraceJSON(self, results): |
| + print 'Writing trace JSON' |
| + results['controllerTraceDataKey'] = 'traceEvents' |
| + with open(self._out_filename, 'w') as json_file: |
| + json.dump(results, json_file) |
| + print '\n wrote file://%s\n' % os.path.abspath(self._out_filename) |
| + |
| + def _WriteTraceHTML(self, results): |
| + """Write the results of systrace to an HTML file.""" |
| + def _read_asset(src_dir, filename): |
| + return open(os.path.join(src_dir, filename)).read() |
| + |
| + print 'Writing trace HTML' |
| + systrace_dir = os.path.abspath(os.path.dirname(__file__)) |
| + html_prefix = _read_asset(systrace_dir, 'prefix.html') |
| + html_suffix = _read_asset(systrace_dir, 'suffix.html') |
| + trace_viewer_html = _read_asset(self._script_dir, |
| + 'systrace_trace_viewer.html') |
| + |
| + # Open the file in binary mode to prevent python from changing the |
| + # line endings. |
| + html_file = open(self._out_filename, 'wb') |
| + html_file.write(html_prefix.replace('{{SYSTRACE_TRACE_VIEWER_HTML}}', |
| + trace_viewer_html)) |
| + |
| + html_file.write('<!-- BEGIN TRACE -->\n') |
| + for (_, data) in results.iteritems(): |
| + html_file.write(' <script class="') |
| + html_file.write('trace-data') |
| + html_file.write('" type="application/text">\n') |
| + html_file.write(convert(data)) |
| + html_file.write(' </script>\n') |
| + html_file.write('<!-- END TRACE -->\n') |
| + |
| + html_file.write(html_suffix) |
| + html_file.close() |
| + print '\n wrote file://%s\n' % os.path.abspath(self._out_filename) |
| + |
| +def convert(data): |
| + """Convert a data element to the format to be output into HTML. |
| + |
| + If the data element is a dictionary or list, JSON-encode it. |
| + If the data element is a string, leave it unchanged. |
| + |
| + Returns: |
| + String to be output into the HTML file. |
| + """ |
| + if isinstance(data, dict) or isinstance(data, list): |
| + return json.dumps(data) |
| + elif isinstance(data, str): |
| + return data |
| + else: |
| + raise ValueError('Invalid data format for HTML output') |
| + |
| +def CreateAgents(options, categories): |
| + """Create systrace agents. |
| + |
| + This function will search systrace agent modules in agent directories and |
| + create the corresponding systrace agents. |
| + Args: |
| + options: The command-line options. |
| + categories: The trace categories to capture. |
| + Returns: |
| + The list of systrace agents. |
| + """ |
| + agent_dirs = [os.path.join(os.path.dirname(__file__), |
| + DEFAULT_AGENT_DIR)] |
| + if options.agent_dirs: |
| + agent_dirs.extend(options.agent_dirs.split(',')) |
| + |
| + agents = [] |
| + for agent_dir in agent_dirs: |
| + if not agent_dir: |
| + continue |
| + for filename in os.listdir(agent_dir): |
| + (module_name, ext) = os.path.splitext(filename) |
| + if (ext != '.py' or module_name == '__init__' |
| + or module_name.endswith('_unittest')): |
| + continue |
| + (f, pathname, data) = imp.find_module(module_name, [agent_dir]) |
| + try: |
| + module = imp.load_module(module_name, f, pathname, data) |
| + finally: |
| + if f: |
| + f.close() |
| + if module: |
| + agent = module.try_create_agent(options, categories) |
| + if not agent: |
| + continue |
| + agents.append(agent) |
| + return agents |