18c2ecf20Sopenharmony_ci#!/usr/bin/env python
28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0-only
38c2ecf20Sopenharmony_ci#
48c2ecf20Sopenharmony_ci# show_deltas: Read list of printk messages instrumented with
58c2ecf20Sopenharmony_ci# time data, and format with time deltas.
68c2ecf20Sopenharmony_ci#
78c2ecf20Sopenharmony_ci# Also, you can show the times relative to a fixed point.
88c2ecf20Sopenharmony_ci#
98c2ecf20Sopenharmony_ci# Copyright 2003 Sony Corporation
108c2ecf20Sopenharmony_ci#
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ciimport sys
138c2ecf20Sopenharmony_ciimport string
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cidef usage():
168c2ecf20Sopenharmony_ci	print ("""usage: show_delta [<options>] <filename>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ciThis program parses the output from a set of printk message lines which
198c2ecf20Sopenharmony_cihave time data prefixed because the CONFIG_PRINTK_TIME option is set, or
208c2ecf20Sopenharmony_cithe kernel command line option "time" is specified. When run with no
218c2ecf20Sopenharmony_cioptions, the time information is converted to show the time delta between
228c2ecf20Sopenharmony_cieach printk line and the next.  When run with the '-b' option, all times
238c2ecf20Sopenharmony_ciare relative to a single (base) point in time.
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ciOptions:
268c2ecf20Sopenharmony_ci  -h            Show this usage help.
278c2ecf20Sopenharmony_ci  -b <base>	Specify a base for time references.
288c2ecf20Sopenharmony_ci		<base> can be a number or a string.
298c2ecf20Sopenharmony_ci		If it is a string, the first message line
308c2ecf20Sopenharmony_ci		which matches (at the beginning of the
318c2ecf20Sopenharmony_ci		line) is used as the time reference.
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ciex: $ dmesg >timefile
348c2ecf20Sopenharmony_ci    $ show_delta -b NET4 timefile
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ciwill show times relative to the line in the kernel output
378c2ecf20Sopenharmony_cistarting with "NET4".
388c2ecf20Sopenharmony_ci""")
398c2ecf20Sopenharmony_ci	sys.exit(1)
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci# returns a tuple containing the seconds and text for each message line
428c2ecf20Sopenharmony_ci# seconds is returned as a float
438c2ecf20Sopenharmony_ci# raise an exception if no timing data was found
448c2ecf20Sopenharmony_cidef get_time(line):
458c2ecf20Sopenharmony_ci	if line[0]!="[":
468c2ecf20Sopenharmony_ci		raise ValueError
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	# split on closing bracket
498c2ecf20Sopenharmony_ci	(time_str, rest) = string.split(line[1:],']',1)
508c2ecf20Sopenharmony_ci	time = string.atof(time_str)
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	#print "time=", time
538c2ecf20Sopenharmony_ci	return (time, rest)
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci# average line looks like:
578c2ecf20Sopenharmony_ci# [    0.084282] VFS: Mounted root (romfs filesystem) readonly
588c2ecf20Sopenharmony_ci# time data is expressed in seconds.useconds,
598c2ecf20Sopenharmony_ci# convert_line adds a delta for each line
608c2ecf20Sopenharmony_cilast_time = 0.0
618c2ecf20Sopenharmony_cidef convert_line(line, base_time):
628c2ecf20Sopenharmony_ci	global last_time
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	try:
658c2ecf20Sopenharmony_ci		(time, rest) = get_time(line)
668c2ecf20Sopenharmony_ci	except:
678c2ecf20Sopenharmony_ci		# if any problem parsing time, don't convert anything
688c2ecf20Sopenharmony_ci		return line
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	if base_time:
718c2ecf20Sopenharmony_ci		# show time from base
728c2ecf20Sopenharmony_ci		delta = time - base_time
738c2ecf20Sopenharmony_ci	else:
748c2ecf20Sopenharmony_ci		# just show time from last line
758c2ecf20Sopenharmony_ci		delta = time - last_time
768c2ecf20Sopenharmony_ci		last_time = time
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	return ("[%5.6f < %5.6f >]" % (time, delta)) + rest
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cidef main():
818c2ecf20Sopenharmony_ci	base_str = ""
828c2ecf20Sopenharmony_ci	filein = ""
838c2ecf20Sopenharmony_ci	for arg in sys.argv[1:]:
848c2ecf20Sopenharmony_ci		if arg=="-b":
858c2ecf20Sopenharmony_ci			base_str = sys.argv[sys.argv.index("-b")+1]
868c2ecf20Sopenharmony_ci		elif arg=="-h":
878c2ecf20Sopenharmony_ci			usage()
888c2ecf20Sopenharmony_ci		else:
898c2ecf20Sopenharmony_ci			filein = arg
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	if not filein:
928c2ecf20Sopenharmony_ci		usage()
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	try:
958c2ecf20Sopenharmony_ci		lines = open(filein,"r").readlines()
968c2ecf20Sopenharmony_ci	except:
978c2ecf20Sopenharmony_ci		print ("Problem opening file: %s" % filein)
988c2ecf20Sopenharmony_ci		sys.exit(1)
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	if base_str:
1018c2ecf20Sopenharmony_ci		print ('base= "%s"' % base_str)
1028c2ecf20Sopenharmony_ci		# assume a numeric base.  If that fails, try searching
1038c2ecf20Sopenharmony_ci		# for a matching line.
1048c2ecf20Sopenharmony_ci		try:
1058c2ecf20Sopenharmony_ci			base_time = float(base_str)
1068c2ecf20Sopenharmony_ci		except:
1078c2ecf20Sopenharmony_ci			# search for line matching <base> string
1088c2ecf20Sopenharmony_ci			found = 0
1098c2ecf20Sopenharmony_ci			for line in lines:
1108c2ecf20Sopenharmony_ci				try:
1118c2ecf20Sopenharmony_ci					(time, rest) = get_time(line)
1128c2ecf20Sopenharmony_ci				except:
1138c2ecf20Sopenharmony_ci					continue
1148c2ecf20Sopenharmony_ci				if string.find(rest, base_str)==1:
1158c2ecf20Sopenharmony_ci					base_time = time
1168c2ecf20Sopenharmony_ci					found = 1
1178c2ecf20Sopenharmony_ci					# stop at first match
1188c2ecf20Sopenharmony_ci					break
1198c2ecf20Sopenharmony_ci			if not found:
1208c2ecf20Sopenharmony_ci				print ('Couldn\'t find line matching base pattern "%s"' % base_str)
1218c2ecf20Sopenharmony_ci				sys.exit(1)
1228c2ecf20Sopenharmony_ci	else:
1238c2ecf20Sopenharmony_ci		base_time = 0.0
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	for line in lines:
1268c2ecf20Sopenharmony_ci		print (convert_line(line, base_time),)
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cimain()
129