1#!/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 23import colorama 24from colorama import Fore 25import argparse 26try: 27 import bt2 28except ImportError: 29 sys.exit("Missing dependency: You need to install python bindings of babeltrace.") 30 31def parse_args(): 32 parser = argparse.ArgumentParser( 33 description=__doc__, 34 formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False) 35 parser.add_argument("-t", "--trace", 36 required=True, 37 help="tracing data (directory with metadata and trace file)") 38 args = parser.parse_args() 39 return args 40 41def main(): 42 colorama.init() 43 44 args = parse_args() 45 46 msg_it = bt2.TraceCollectionMessageIterator(args.trace) 47 last_event_ns_from_origin = None 48 timeline = [] 49 50 def get_thread(name): 51 for t in timeline: 52 if t.get('name', None) == name and t.get('in', 0 ) != 0 and not t.get('out', None): 53 return t 54 return {} 55 56 for msg in msg_it: 57 58 if not isinstance(msg, bt2._EventMessageConst): 59 continue 60 61 ns_from_origin = msg.default_clock_snapshot.ns_from_origin 62 event = msg.event 63 # Compute the time difference since the last event message. 64 diff_s = 0 65 66 if last_event_ns_from_origin is not None: 67 diff_s = (ns_from_origin - last_event_ns_from_origin) / 1e9 68 69 dt = datetime.datetime.fromtimestamp(ns_from_origin / 1e9) 70 71 if event.name in [ 72 'thread_switched_out', 73 'thread_switched_in', 74 'thread_pending', 75 'thread_ready', 76 'thread_resume', 77 'thread_suspend', 78 'thread_create', 79 'thread_abort' 80 ]: 81 82 cpu = event.payload_field.get("cpu", None) 83 thread_id = event.payload_field.get("thread_id", None) 84 thread_name = event.payload_field.get("name", None) 85 86 th = {} 87 if event.name in ['thread_switched_out', 'thread_switched_in'] and cpu is not None: 88 cpu_string = f"(cpu: {cpu})" 89 else: 90 cpu_string = "" 91 92 if thread_name: 93 print(f"{dt} (+{diff_s:.6f} s): {event.name}: {thread_name} {cpu_string}") 94 elif thread_id: 95 print(f"{dt} (+{diff_s:.6f} s): {event.name}: {thread_id} {cpu_string}") 96 else: 97 print(f"{dt} (+{diff_s:.6f} s): {event.name}") 98 99 if event.name in ['thread_switched_out', 'thread_switched_in']: 100 if thread_name: 101 th = get_thread(thread_name) 102 if not th: 103 th['name'] = thread_name 104 else: 105 th = get_thread(thread_id) 106 if not th: 107 th['name'] = thread_id 108 109 if event.name in ['thread_switched_out']: 110 th['out'] = ns_from_origin 111 tin = th.get('in', None) 112 tout = th.get('out', None) 113 if tout is not None and tin is not None: 114 diff = tout - tin 115 th['runtime'] = diff 116 elif event.name in ['thread_switched_in']: 117 th['in'] = ns_from_origin 118 119 timeline.append(th) 120 121 elif event.name in ['thread_info']: 122 stack_size = event.payload_field['stack_size'] 123 print(f"{dt} (+{diff_s:.6f} s): {event.name} (Stack size: {stack_size})") 124 elif event.name in ['start_call', 'end_call']: 125 if event.payload_field['id'] == 39: 126 c = Fore.GREEN 127 elif event.payload_field['id'] in [37, 38]: 128 c = Fore.CYAN 129 else: 130 c = Fore.YELLOW 131 print(c + f"{dt} (+{diff_s:.6f} s): {event.name} {event.payload_field['id']}" + Fore.RESET) 132 elif event.name in ['semaphore_init', 'semaphore_take', 'semaphore_give']: 133 c = Fore.CYAN 134 print(c + f"{dt} (+{diff_s:.6f} s): {event.name} ({event.payload_field['id']})" + Fore.RESET) 135 elif event.name in ['mutex_init', 'mutex_take', 'mutex_give']: 136 c = Fore.MAGENTA 137 print(c + f"{dt} (+{diff_s:.6f} s): {event.name} ({event.payload_field['id']})" + Fore.RESET) 138 139 else: 140 print(f"{dt} (+{diff_s:.6f} s): {event.name}") 141 142 last_event_ns_from_origin = ns_from_origin 143 144if __name__=="__main__": 145 main() 146