blob: 854f07b125c01eb397a0ad13eba7fe13a49303aa [file] [log] [blame]
Jamie Gennis92791472012-03-05 17:33:58 -08001#!/usr/bin/env python
2
3#
4# Copyright 2012, The Android Open Source Project
5#
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18
19"""Android system-wide tracing utility.
20
21This is a tool for capturing a trace that includes data from both userland and
22the kernel. It creates an HTML file for visualizing the trace.
23"""
24
25import optparse, os, subprocess, sys
26
27def main():
28 parser = optparse.OptionParser()
29 parser.add_option('-o', dest='output_file', help='write HTML to FILE',
30 default='trace.html', metavar='FILE')
31 parser.add_option('-t', '--time', dest='trace_time', type='int',
32 help='trace for N seconds', metavar='N')
33 parser.add_option('-w', '--workqueue', dest='trace_workqueue', default=False,
34 action='store_true', help='trace the kernel workqueues')
35 options, args = parser.parse_args()
36
37 atrace_args = ['adb', 'shell', 'atrace', '-s']
38 if options.trace_workqueue:
39 atrace_args.append('-w')
40 if options.trace_time is not None:
41 if options.trace_time > 0:
42 atrace_args.extend(['-t', str(options.trace_time)])
43 else:
44 parser.error('the trace time must be a positive number')
45
46 html_filename = options.output_file
47 html_file = open(html_filename, 'w')
48 html_file.write(html_prefix)
49
50 trace_started = False
51 popen = subprocess.Popen(atrace_args, stdout=subprocess.PIPE,
52 stderr=subprocess.PIPE)
53 while True:
54 stdout, stderr = popen.communicate()
55 if len(stderr) > 0:
56 print sys.stderr, stderr
57 break
58 if len(stdout) > 0:
59 if not trace_started:
60 lines = stdout.splitlines()
61 for i, line in enumerate(lines):
62 if line == 'TRACE:':
63 print "downloading trace...",
64 sys.stdout.flush()
65 stdout = '\n'.join(lines[i+1:])
66 trace_started = True
67 break
68 else:
69 print line
70 sys.stdout.flush()
71 html_stdout = stdout.replace('\n', '\\n\\\n').replace('\r', '')
72 if len(html_stdout) > 0:
73 html_file.write(html_stdout)
74 result = popen.poll()
75 if result is not None:
76 break
77 if result != 0:
78 print sys.stderr, 'adb returned error code %d' % result
79 else:
80 html_file.write(html_suffix)
81 html_file.close()
82 print "done\n\n wrote file://%s/%s\n" % (os.getcwd(), options.output_file)
83
84html_prefix = """<!DOCTYPE HTML>
85<html>
86<head i18n-values="dir:textdirection;">
87<title>Android System Trace</title>
88<link rel="stylesheet" href="http://www.corp.google.com/~jgennis/android_tracing/viewer/timeline.css">
89<link rel="stylesheet" href="http://www.corp.google.com/~jgennis/android_tracing/viewer/timeline_view.css">
90<script src="http://www.corp.google.com/~jgennis/android_tracing/0.1/shared/js/cr.js"></script>
91<script src="http://www.corp.google.com/~jgennis/android_tracing/0.1/shared/js/cr/event_target.js"></script>
92<script src="http://www.corp.google.com/~jgennis/android_tracing/0.1/shared/js/cr/ui.js"></script>
93<script src="http://www.corp.google.com/~jgennis/android_tracing/0.1/shared/js/util.js"></script>
94<script src="http://www.corp.google.com/~jgennis/android_tracing/0.1/viewer/timeline_model.js"></script>
95<script src="http://www.corp.google.com/~jgennis/android_tracing/0.1/viewer/linux_perf_importer.js"></script>
96<script src="http://www.corp.google.com/~jgennis/android_tracing/0.1/viewer/trace_event_importer.js"></script>
97<script src="http://www.corp.google.com/~jgennis/android_tracing/0.1/viewer/sorted_array_utils.js"></script>
98<script src="http://www.corp.google.com/~jgennis/android_tracing/0.1/viewer/measuring_stick.js"></script>
99<script src="http://www.corp.google.com/~jgennis/android_tracing/0.1/viewer/timeline.js"></script>
100<script src="http://www.corp.google.com/~jgennis/android_tracing/0.1/viewer/timeline_track.js"></script>
101<script src="http://www.corp.google.com/~jgennis/android_tracing/0.1/viewer/timeline_view.js"></script>
102<script src="http://www.corp.google.com/~jgennis/android_tracing/0.1/viewer/fast_rect_renderer.js"></script>
103<script src="http://www.corp.google.com/~jgennis/android_tracing/0.1/viewer/test_utils.js"></script>
104<style>
105 .view {
106 overflow: hidden;
107 position: absolute;
108 top: 0;
109 bottom: 0;
110 left: 0;
111 right: 0;
112 }
113</style>
114</head>
115<body>
116 <div class="view">
117 </div>
118 <script>
119 var linuxPerfData = "\\
120"""
121
122html_suffix = """\\n\\
123 dummy-0000 [000] 0.0: 0: trace_event_clock_sync: parent_ts=0.0\\n";
124 var timelineViewEl;
125 function onLoad() {
126 reload();
127 }
128 function reload() {
129 if (!linuxPerfData)
130 return;
131
132 var m = new tracing.TimelineModel();
133 m.importEvents("[]", true, [linuxPerfData]);
134
135 timelineViewEl = document.querySelector('.view');
136 cr.ui.decorate(timelineViewEl, tracing.TimelineView);
137 timelineViewEl.model = m;
138 timelineViewEl.tabIndex = 1;
139 timelineViewEl.timeline.focusElement = timelineViewEl;
140 }
141
142 document.addEventListener('DOMContentLoaded', onLoad);
143 </script>
144</body>
145</html>
146"""
147
148if __name__ == '__main__':
149 main()