blob: 5b52bffa332d5f72a73b495dacd165db2fd61325 [file] [log] [blame]
Anas Nashif5ab117f2020-08-20 16:19:08 -04001#!/usr/bin/env python3
2#
3# Copyright (c) 2020 Intel Corporation.
4#
5# SPDX-License-Identifier: Apache-2.0
6"""
7Script to parse CTF data and print to the screen in a custom and colorful
8format.
9
10Generate trace using samples/subsys/tracing for example:
11
12 west build -b qemu_x86 samples/subsys/tracing -t run \
13 -- -DCONF_FILE=prj_uart_ctf.conf
14
15 mkdir ctf
16 cp build/channel0_0 ctf/
17 cp subsys/tracing/ctf/tsdl/metadata ctf/
18 ./scripts/tracing/parse_ctf.py -t ctf
19"""
20
21import sys
22import datetime
23from colorama import Fore
24import argparse
25try:
26 import bt2
27except ImportError:
28 sys.exit("Missing dependency: You need to install python bindings of babletrace.")
29
30def parse_args():
31 parser = argparse.ArgumentParser(
32 description=__doc__,
33 formatter_class=argparse.RawDescriptionHelpFormatter)
34 parser.add_argument("-t", "--trace",
35 required=True,
36 help="tracing data (directory with metadata and trace file)")
37 args = parser.parse_args()
38 return args
39
40def main():
41 args = parse_args()
42
43 msg_it = bt2.TraceCollectionMessageIterator(args.trace)
44 last_event_ns_from_origin = None
45 timeline = []
46
47 def get_thread(name):
48 for t in timeline:
49 if t.get('name', None) == name and t.get('in', 0 ) != 0 and not t.get('out', None):
50 return t
51 return {}
52
53 for msg in msg_it:
54
55 if not isinstance(msg, bt2._EventMessageConst):
56 continue
57
58 ns_from_origin = msg.default_clock_snapshot.ns_from_origin
59 event = msg.event
60 # Compute the time difference since the last event message.
61 diff_s = 0
62
63 if last_event_ns_from_origin is not None:
64 diff_s = (ns_from_origin - last_event_ns_from_origin) / 1e9
65
66 dt = datetime.datetime.fromtimestamp(ns_from_origin / 1e9)
67
68 if event.name in [
69 'thread_switched_out',
70 'thread_switched_in',
71 'thread_pending',
72 'thread_ready',
73 'thread_resume',
74 'thread_suspend',
75 'thread_create',
76 'thread_abort'
77 ]:
78
79 cpu = event.payload_field.get("cpu", None)
80 thread_id = event.payload_field.get("thread_id", None)
81 thread_name = event.payload_field.get("name", None)
82
83 th = {}
84 if event.name in ['thread_switched_out', 'thread_switched_in'] and cpu is not None:
85 cpu_string = f"(cpu: {cpu})"
86 else:
87 cpu_string = ""
88
89 if thread_name:
90 print(f"{dt} (+{diff_s:.6f} s): {event.name}: {thread_name} {cpu_string}")
91 elif thread_id:
92 print(f"{dt} (+{diff_s:.6f} s): {event.name}: {thread_id} {cpu_string}")
93 else:
94 print(f"{dt} (+{diff_s:.6f} s): {event.name}")
95
96 if event.name in ['thread_switched_out', 'thread_switched_in']:
97 if thread_name:
98 th = get_thread(thread_name)
99 if not th:
100 th['name'] = thread_name
101 else:
102 th = get_thread(thread_id)
103 if not th:
104 th['name'] = thread_id
105
106 if event.name in ['thread_switched_out']:
107 th['out'] = ns_from_origin
108 tin = th.get('in', None)
109 tout = th.get('out', None)
110 if tout is not None and tin is not None:
111 diff = (tout - tin)
112 th['runtime'] = diff
113 elif event.name in ['thread_switched_in']:
114 th['in'] = ns_from_origin
115
116 timeline.append(th)
117
118 elif event.name in ['thread_info']:
119 stack_size = event.payload_field['stack_size']
120 print(f"{dt} (+{diff_s:.6f} s): {event.name} (Stack size: {stack_size})")
121 elif event.name in ['start_call', 'end_call']:
122 if event.payload_field['id'] == 39:
123 c = Fore.GREEN
124 elif event.payload_field['id'] in [37, 38]:
125 c = Fore.CYAN
126 else:
127 c = Fore.YELLOW
128 print(c + f"{dt} (+{diff_s:.6f} s): {event.name} {event.payload_field['id']}" + Fore.RESET)
129 elif event.name in ['semaphore_init', 'semaphore_take', 'semaphore_give']:
130 c = Fore.CYAN
131 print(c + f"{dt} (+{diff_s:.6f} s): {event.name} ({event.payload_field['id']})" + Fore.RESET)
132 elif event.name in ['mutex_init', 'mutex_take', 'mutex_give']:
133 c = Fore.MAGENTA
134 print(c + f"{dt} (+{diff_s:.6f} s): {event.name} ({event.payload_field['id']})" + Fore.RESET)
135
136 else:
137 print(f"{dt} (+{diff_s:.6f} s): {event.name}")
138
139 last_event_ns_from_origin = ns_from_origin
140
141if __name__=="__main__":
142 main()