zephyr/scripts/tracing/parse_ctf.py
Jamie McCrae ec7044437e treewide: Disable automatic argparse argument shortening
Disables allowing the python argparse library from automatically
shortening command line arguments, this prevents issues whereby
a new command is added and code that wrongly uses the shortened
command of an existing argument which is the same as the new
command being added will silently change script behaviour.

Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
2023-01-26 20:12:36 +09:00

145 lines
4.9 KiB
Python

#!/usr/bin/env python3
#
# Copyright (c) 2020 Intel Corporation.
#
# SPDX-License-Identifier: Apache-2.0
"""
Script to parse CTF data and print to the screen in a custom and colorful
format.
Generate trace using samples/subsys/tracing for example:
west build -b qemu_x86 samples/subsys/tracing -t run \
-- -DCONF_FILE=prj_uart_ctf.conf
mkdir ctf
cp build/channel0_0 ctf/
cp subsys/tracing/ctf/tsdl/metadata ctf/
./scripts/tracing/parse_ctf.py -t ctf
"""
import sys
import datetime
import colorama
from colorama import Fore
import argparse
try:
import bt2
except ImportError:
sys.exit("Missing dependency: You need to install python bindings of babletrace.")
def parse_args():
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False)
parser.add_argument("-t", "--trace",
required=True,
help="tracing data (directory with metadata and trace file)")
args = parser.parse_args()
return args
def main():
colorama.init()
args = parse_args()
msg_it = bt2.TraceCollectionMessageIterator(args.trace)
last_event_ns_from_origin = None
timeline = []
def get_thread(name):
for t in timeline:
if t.get('name', None) == name and t.get('in', 0 ) != 0 and not t.get('out', None):
return t
return {}
for msg in msg_it:
if not isinstance(msg, bt2._EventMessageConst):
continue
ns_from_origin = msg.default_clock_snapshot.ns_from_origin
event = msg.event
# Compute the time difference since the last event message.
diff_s = 0
if last_event_ns_from_origin is not None:
diff_s = (ns_from_origin - last_event_ns_from_origin) / 1e9
dt = datetime.datetime.fromtimestamp(ns_from_origin / 1e9)
if event.name in [
'thread_switched_out',
'thread_switched_in',
'thread_pending',
'thread_ready',
'thread_resume',
'thread_suspend',
'thread_create',
'thread_abort'
]:
cpu = event.payload_field.get("cpu", None)
thread_id = event.payload_field.get("thread_id", None)
thread_name = event.payload_field.get("name", None)
th = {}
if event.name in ['thread_switched_out', 'thread_switched_in'] and cpu is not None:
cpu_string = f"(cpu: {cpu})"
else:
cpu_string = ""
if thread_name:
print(f"{dt} (+{diff_s:.6f} s): {event.name}: {thread_name} {cpu_string}")
elif thread_id:
print(f"{dt} (+{diff_s:.6f} s): {event.name}: {thread_id} {cpu_string}")
else:
print(f"{dt} (+{diff_s:.6f} s): {event.name}")
if event.name in ['thread_switched_out', 'thread_switched_in']:
if thread_name:
th = get_thread(thread_name)
if not th:
th['name'] = thread_name
else:
th = get_thread(thread_id)
if not th:
th['name'] = thread_id
if event.name in ['thread_switched_out']:
th['out'] = ns_from_origin
tin = th.get('in', None)
tout = th.get('out', None)
if tout is not None and tin is not None:
diff = (tout - tin)
th['runtime'] = diff
elif event.name in ['thread_switched_in']:
th['in'] = ns_from_origin
timeline.append(th)
elif event.name in ['thread_info']:
stack_size = event.payload_field['stack_size']
print(f"{dt} (+{diff_s:.6f} s): {event.name} (Stack size: {stack_size})")
elif event.name in ['start_call', 'end_call']:
if event.payload_field['id'] == 39:
c = Fore.GREEN
elif event.payload_field['id'] in [37, 38]:
c = Fore.CYAN
else:
c = Fore.YELLOW
print(c + f"{dt} (+{diff_s:.6f} s): {event.name} {event.payload_field['id']}" + Fore.RESET)
elif event.name in ['semaphore_init', 'semaphore_take', 'semaphore_give']:
c = Fore.CYAN
print(c + f"{dt} (+{diff_s:.6f} s): {event.name} ({event.payload_field['id']})" + Fore.RESET)
elif event.name in ['mutex_init', 'mutex_take', 'mutex_give']:
c = Fore.MAGENTA
print(c + f"{dt} (+{diff_s:.6f} s): {event.name} ({event.payload_field['id']})" + Fore.RESET)
else:
print(f"{dt} (+{diff_s:.6f} s): {event.name}")
last_event_ns_from_origin = ns_from_origin
if __name__=="__main__":
main()