blob: 4e69af57bd3c29d2af4cb47d97a7d1aadb441146 [file] [log] [blame]
Chris Craikb2cbf152015-07-28 16:26:29 -07001# Copyright (c) 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 codecs
6import base64
7import gzip
8import json
9import optparse
10import os
11import StringIO
12import sys
13
14tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
15 '..', '..'))
16if tracing_path not in sys.path:
17 sys.path.append(tracing_path)
18
19from tracing import tracing_project
20from tvcm import generate
21
22
23def Main(args):
24
25 parser = optparse.OptionParser(
26 usage="%prog <options> trace_file1 [trace_file2 ...]",
27 epilog="""Takes the provided trace file and produces a standalone html
28file that contains both the trace and the trace viewer.""")
29
30 project = tracing_project.TracingProject()
31 project.AddConfigNameOptionToParser(parser)
32
33 parser.add_option(
34 "--output", dest="output",
35 help='Where to put the generated result. If not ' +
36 'given, the trace filename is used, with an html suffix.')
37 parser.add_option(
38 "--quiet", action='store_true',
39 help='Dont print the output file name')
40 options, args = parser.parse_args(args)
41 if len(args) == 0:
42 parser.error('At least one trace file required')
43
44 if options.output:
45 output_filename = options.output
46 elif len(args) > 1:
47 parser.error('Must specify --output if >1 trace file')
48 else:
49 namepart = os.path.splitext(args[0])[0]
50 output_filename = namepart + '.html'
51
52 with codecs.open(output_filename, mode='w', encoding='utf-8') as f:
53 WriteHTMLForTracesToFile(args, f, config_name=options.config_name)
54
55 if not options.quiet:
56 print output_filename
57 return 0
58
59
60class ViewerDataScript(generate.ExtraScript):
61
62 def __init__(self, trace_data_string, mime_type):
63 super(ViewerDataScript, self).__init__()
64 self._trace_data_string = trace_data_string
65 self._mime_type = mime_type
66
67 def WriteToFile(self, output_file):
68 output_file.write('<script id="viewer-data" type="%s">\n' % self._mime_type)
69 compressed_trace = StringIO.StringIO()
70 with gzip.GzipFile(fileobj=compressed_trace, mode='w') as f:
71 f.write(self._trace_data_string)
72 b64_content = base64.b64encode(compressed_trace.getvalue())
73 output_file.write(b64_content)
74 output_file.write('\n</script>\n')
75
76
77def WriteHTMLForTraceDataToFile(trace_data_list,
78 title, output_file,
79 config_name=None):
80 project = tracing_project.TracingProject()
81
82 if config_name is None:
83 config_name = project.GetDefaultConfigName()
84
85 modules = [
86 'trace2html',
87 'extras.importer.gzip_importer', # Must have this regardless of config.
88 project.GetModuleNameForConfigName(config_name)
89 ]
90
91 load_sequence = project.CalcLoadSequenceForModuleNames(modules)
92
93 scripts = []
94 for trace_data in trace_data_list:
95 # If the object was previously decoded from valid JSON data (e.g., in
96 # WriteHTMLForTracesToFile), it will be a JSON object at this point and we
97 # should re-serialize it into a string. Other types of data will be already
98 # be strings.
99 if not isinstance(trace_data, basestring):
100 trace_data = json.dumps(trace_data)
101 mime_type = 'application/json'
102 else:
103 mime_type = 'text/plain'
104 scripts.append(ViewerDataScript(trace_data, mime_type))
105 generate.GenerateStandaloneHTMLToFile(
106 output_file, load_sequence, title, extra_scripts=scripts)
107
108
109def WriteHTMLForTracesToFile(trace_filenames, output_file, config_name=None):
110 trace_data_list = []
111 for filename in trace_filenames:
112 with open(filename, 'r') as f:
113 trace_data = f.read()
114 try:
115 trace_data = json.loads(trace_data)
116 except ValueError:
117 pass
118 trace_data_list.append(trace_data)
119
120 title = "Trace from %s" % ','.join(trace_filenames)
121 WriteHTMLForTraceDataToFile(trace_data_list, title, output_file, config_name)