xref: /aosp_15_r20/external/perfetto/tools/open_trace_in_ui (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*6dbdd20aSAndroid Build Coastguard Worker# Copyright (C) 2021 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker#
4*6dbdd20aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker#
8*6dbdd20aSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker#
10*6dbdd20aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker# limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker
16*6dbdd20aSAndroid Build Coastguard Workerimport argparse
17*6dbdd20aSAndroid Build Coastguard Workerimport http.server
18*6dbdd20aSAndroid Build Coastguard Workerimport os
19*6dbdd20aSAndroid Build Coastguard Workerimport socketserver
20*6dbdd20aSAndroid Build Coastguard Workerimport sys
21*6dbdd20aSAndroid Build Coastguard Workerimport webbrowser
22*6dbdd20aSAndroid Build Coastguard Worker
23*6dbdd20aSAndroid Build Coastguard Worker
24*6dbdd20aSAndroid Build Coastguard Workerclass ANSI:
25*6dbdd20aSAndroid Build Coastguard Worker  END = '\033[0m'
26*6dbdd20aSAndroid Build Coastguard Worker  BOLD = '\033[1m'
27*6dbdd20aSAndroid Build Coastguard Worker  RED = '\033[91m'
28*6dbdd20aSAndroid Build Coastguard Worker  BLACK = '\033[30m'
29*6dbdd20aSAndroid Build Coastguard Worker  BLUE = '\033[94m'
30*6dbdd20aSAndroid Build Coastguard Worker  BG_YELLOW = '\033[43m'
31*6dbdd20aSAndroid Build Coastguard Worker  BG_BLUE = '\033[44m'
32*6dbdd20aSAndroid Build Coastguard Worker
33*6dbdd20aSAndroid Build Coastguard Worker
34*6dbdd20aSAndroid Build Coastguard Worker# HTTP Server used to open the trace in the browser.
35*6dbdd20aSAndroid Build Coastguard Workerclass HttpHandler(http.server.SimpleHTTPRequestHandler):
36*6dbdd20aSAndroid Build Coastguard Worker
37*6dbdd20aSAndroid Build Coastguard Worker  def end_headers(self):
38*6dbdd20aSAndroid Build Coastguard Worker    self.send_header('Access-Control-Allow-Origin', self.server.allow_origin)
39*6dbdd20aSAndroid Build Coastguard Worker    self.send_header('Cache-Control', 'no-cache')
40*6dbdd20aSAndroid Build Coastguard Worker    super().end_headers()
41*6dbdd20aSAndroid Build Coastguard Worker
42*6dbdd20aSAndroid Build Coastguard Worker  def do_GET(self):
43*6dbdd20aSAndroid Build Coastguard Worker    if self.path != '/' + self.server.expected_fname:
44*6dbdd20aSAndroid Build Coastguard Worker      self.send_error(404, 'File not found')
45*6dbdd20aSAndroid Build Coastguard Worker      return
46*6dbdd20aSAndroid Build Coastguard Worker
47*6dbdd20aSAndroid Build Coastguard Worker    self.server.fname_get_completed = True
48*6dbdd20aSAndroid Build Coastguard Worker    super().do_GET()
49*6dbdd20aSAndroid Build Coastguard Worker
50*6dbdd20aSAndroid Build Coastguard Worker  def do_POST(self):
51*6dbdd20aSAndroid Build Coastguard Worker    self.send_error(404, 'File not found')
52*6dbdd20aSAndroid Build Coastguard Worker
53*6dbdd20aSAndroid Build Coastguard Worker
54*6dbdd20aSAndroid Build Coastguard Workerdef prt(msg, colors=ANSI.END):
55*6dbdd20aSAndroid Build Coastguard Worker  print(colors + msg + ANSI.END)
56*6dbdd20aSAndroid Build Coastguard Worker
57*6dbdd20aSAndroid Build Coastguard Worker
58*6dbdd20aSAndroid Build Coastguard Workerdef open_trace(path, open_browser, origin):
59*6dbdd20aSAndroid Build Coastguard Worker  # We reuse the HTTP+RPC port because it's the only one allowed by the CSP.
60*6dbdd20aSAndroid Build Coastguard Worker  PORT = 9001
61*6dbdd20aSAndroid Build Coastguard Worker  path = os.path.abspath(path)
62*6dbdd20aSAndroid Build Coastguard Worker  os.chdir(os.path.dirname(path))
63*6dbdd20aSAndroid Build Coastguard Worker  fname = os.path.basename(path)
64*6dbdd20aSAndroid Build Coastguard Worker  socketserver.TCPServer.allow_reuse_address = True
65*6dbdd20aSAndroid Build Coastguard Worker  with socketserver.TCPServer(('127.0.0.1', PORT), HttpHandler) as httpd:
66*6dbdd20aSAndroid Build Coastguard Worker    address = f'{origin}/#!/?url=http://127.0.0.1:{PORT}/{fname}&referrer=open_trace_in_ui'
67*6dbdd20aSAndroid Build Coastguard Worker    if open_browser:
68*6dbdd20aSAndroid Build Coastguard Worker      webbrowser.open_new_tab(address)
69*6dbdd20aSAndroid Build Coastguard Worker    else:
70*6dbdd20aSAndroid Build Coastguard Worker      print(f'Open URL in browser: {address}')
71*6dbdd20aSAndroid Build Coastguard Worker
72*6dbdd20aSAndroid Build Coastguard Worker    httpd.expected_fname = fname
73*6dbdd20aSAndroid Build Coastguard Worker    httpd.fname_get_completed = None
74*6dbdd20aSAndroid Build Coastguard Worker    httpd.allow_origin = origin
75*6dbdd20aSAndroid Build Coastguard Worker    while httpd.fname_get_completed is None:
76*6dbdd20aSAndroid Build Coastguard Worker      httpd.handle_request()
77*6dbdd20aSAndroid Build Coastguard Worker
78*6dbdd20aSAndroid Build Coastguard Worker
79*6dbdd20aSAndroid Build Coastguard Workerdef main():
80*6dbdd20aSAndroid Build Coastguard Worker  examples = '\n'.join([
81*6dbdd20aSAndroid Build Coastguard Worker      ANSI.BOLD + 'Examples:' + ANSI.END,
82*6dbdd20aSAndroid Build Coastguard Worker      '  tools/open_trace_in_ui trace.pftrace',
83*6dbdd20aSAndroid Build Coastguard Worker  ])
84*6dbdd20aSAndroid Build Coastguard Worker  parser = argparse.ArgumentParser(
85*6dbdd20aSAndroid Build Coastguard Worker      epilog=examples, formatter_class=argparse.RawTextHelpFormatter)
86*6dbdd20aSAndroid Build Coastguard Worker
87*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument('positional_trace', metavar='trace', nargs='?')
88*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
89*6dbdd20aSAndroid Build Coastguard Worker      '-n', '--no-open-browser', action='store_true', default=False)
90*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument('--origin', default='https://ui.perfetto.dev')
91*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
92*6dbdd20aSAndroid Build Coastguard Worker      '-i', '--trace', help='input filename (overrides positional argument)')
93*6dbdd20aSAndroid Build Coastguard Worker
94*6dbdd20aSAndroid Build Coastguard Worker  args = parser.parse_args()
95*6dbdd20aSAndroid Build Coastguard Worker  open_browser = not args.no_open_browser
96*6dbdd20aSAndroid Build Coastguard Worker
97*6dbdd20aSAndroid Build Coastguard Worker  trace_file = None
98*6dbdd20aSAndroid Build Coastguard Worker  if args.positional_trace is not None:
99*6dbdd20aSAndroid Build Coastguard Worker    trace_file = args.positional_trace
100*6dbdd20aSAndroid Build Coastguard Worker  if args.trace is not None:
101*6dbdd20aSAndroid Build Coastguard Worker    trace_file = args.trace
102*6dbdd20aSAndroid Build Coastguard Worker
103*6dbdd20aSAndroid Build Coastguard Worker  if trace_file is None:
104*6dbdd20aSAndroid Build Coastguard Worker    prt('Please specify trace file name', ANSI.RED)
105*6dbdd20aSAndroid Build Coastguard Worker    sys.exit(1)
106*6dbdd20aSAndroid Build Coastguard Worker  elif not os.path.exists(trace_file):
107*6dbdd20aSAndroid Build Coastguard Worker    prt('%s not found ' % trace_file, ANSI.RED)
108*6dbdd20aSAndroid Build Coastguard Worker    sys.exit(1)
109*6dbdd20aSAndroid Build Coastguard Worker
110*6dbdd20aSAndroid Build Coastguard Worker  prt('Opening the trace (%s) in the browser' % trace_file)
111*6dbdd20aSAndroid Build Coastguard Worker  open_trace(trace_file, open_browser, args.origin)
112*6dbdd20aSAndroid Build Coastguard Worker
113*6dbdd20aSAndroid Build Coastguard Worker
114*6dbdd20aSAndroid Build Coastguard Workerif __name__ == '__main__':
115*6dbdd20aSAndroid Build Coastguard Worker  sys.exit(main())
116