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