zephyr/scripts/tracing/parse_ctf.py
Daniel DeGrasse 66577a9d23 tracing: add named event trace
Add support for a "named event" trace. This trace is intentionally not
used by the system. The purpose of this trace is to allow driver or
application developers to quickly add tracing for events for debug
purposes, and to provide an example of how tracing subsystems can be
extended with additional trace identifiers.

Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
2024-10-17 10:46:52 -04:00

150 lines
5.1 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 babeltrace.")
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)
elif event.name in ['named_event']:
name = event.payload_field['name']
arg0 = event.payload_field['arg0']
arg1 = event.payload_field['arg1']
print(f"{dt} (+{diff_s:.6f} s): {event.name} (name: {name}, arg0: {arg0} arg1: {arg1})")
else:
print(f"{dt} (+{diff_s:.6f} s): {event.name}")
last_event_ns_from_origin = ns_from_origin
if __name__=="__main__":
main()