/usr/share/pyshared/timechart/backends/ftrace.py is in pytimechart 1.0.0~rc1-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | import re
import sys,os
from timechart.plugin import get_plugins_additional_ftrace_parsers
from pyface.api import ProgressDialog
# take the TP_printk from the /include/trace/events dir
# syntax is event_name, printk, printk_args...
events_desc = [
('sched_switch', 'task %s:%d [%d] (%s) ==> %s:%d [%d]',
'prev_comm', 'prev_pid', 'prev_prio','prev_state' ,
'next_comm', 'next_pid', 'next_prio'),
('sched_switch', 'task %s:%d [%d] ==> %s:%d [%d]',
'prev_comm', 'prev_pid', 'prev_prio' ,
'next_comm', 'next_pid', 'next_prio'),
('sched_switch', 'prev_comm=%s prev_pid=%d prev_prio=%d prev_state=%s ==> next_comm=%s next_pid=%d next_prio=%d',
'prev_comm', 'prev_pid', 'prev_prio' , 'prev_state',
'next_comm', 'next_pid', 'next_prio'),
('sched_wakeup','task %s:%d [%d] success=%d [%d]','comm', 'pid', 'prio', 'success', 'cpu'),
('sched_wakeup','task %s:%d [%d] success=%d','comm', 'pid', 'prio', 'success'),
('sched_wakeup','comm=%s pid=%d prio=%d success=%d target_cpu=%d','comm', 'pid', 'prio', 'success', 'cpu'),
]
events_desc += get_plugins_additional_ftrace_parsers()
# pre process our descriptions to transform it into re
events_re = {}
num_func = 0
for event in events_desc:
name = event[0]
printk = event[1]
args = event[2:]
args_l = []
for i in '()[]':
printk = printk.replace(i,'\\'+i)
# we replace %d %s by the equivalent regular expression, and keep the type in memory for later
i = 0
func = "def my_dispatch_func%d(event,group):\n"%(num_func)
for arg in args:
idx = printk.index('%')
format = printk[idx+1]
if format=='d':
filt=int
regex="([-0-9]+)"
func+=" event['%s'] = int(group[%d])\n"%(arg,i)
elif format=='s':
filt=str
regex="(.*)"
func+=" event['%s'] = group[%d]\n"%(arg,i)
printk = printk.replace("%"+format,regex,1)
args_l.append((arg,filt))
i+=1
if not events_re.has_key(name):
events_re[name] = []
exec func
events_re[name].append((name,re.compile(printk),eval("my_dispatch_func%d"%num_func)))
num_func+=1
# event class passed to callback, this is more convenient than passing a dictionary
class Event:
def __init__(self,event):
self.__dict__=event
def __repr__(self):
ret = ""
for k in self.__dict__:
ret += "%s: %s, "%(k,str(self.__dict__[k]))
return ret
# seamlessly open gziped of raw text files
def ftrace_open(filename):
if filename.endswith(".gz"):
import gzip
return gzip.open(filename,"r")
elif filename.endswith(".lzma"):
try:
import lzma
except:
raise Exception("lzma module could not be imported. Please install python-lzma to seamlessly open lzma compressed file: http://pypi.python.org/pypi/pyliblzma")
return lzma.LZMAFile(filename,"r")
else:
return open(filename,"r")
#@profile
def parse_ftrace(filename,callback):
fid = ftrace_open(filename)
progress = ProgressDialog(title="ftrace", message="loading %s..."%(os.path.basename(filename)), max=100, show_time=True, can_cancel=True)
progress.open()
try:
fid.seek(0,2)
except ValueError:
# gzip do not support seek end
# do we uncompress everything. :-/
# parsing is already far slower than uncompressing.
while fid.read(1024):
pass
totsize = fid.tell()
fid.seek(0,0)
last_percent = 0
# the base regular expressions
event_re = re.compile(
r'\s*(.+)-([0-9]+)\s+\[([0-9]+)\]\s+([0-9.]+): ([^:]*): (.*)')
function_re = re.compile(
r'\s*(.+)-([0-9]+)\s+\[([0-9]+)\]\s+([0-9.]+): (.*) <-(.*)')
last_timestamp = 0
linenumber = 0
for line in fid:
percent = int(fid.tell()*100./totsize)
if percent != last_percent:
last_percent = percent
(cont, skip) = progress.update(percent)
if not cont or skip:
break
linenumber+=1
line = line.rstrip()
res = event_re.match(line)
if res:
groups = res.groups()
event_name = groups[4]
event = {
'linenumber': linenumber,
'common_comm' : groups[0],
'common_pid' : int(groups[1]),
'common_cpu' : int(groups[2]),
'timestamp' : int(float(groups[3])*1000000),
'event' : event_name,
'event_arg' : groups[5]
}
last_timestamp = event['timestamp']
to_match = event['event_arg']
try:
for name,regex,func in events_re[event_name]:
res = regex.search(to_match)
if res:
func(event,res.groups())
except KeyError:
pass
callback(Event(event))
continue
res = function_re.match(line)
if res:
event = {
'linenumber': linenumber,
'common_comm' : res.group(1),
'common_pid' : int(res.group(2)),
'common_cpu' : int(res.group(3)),
'timestamp' : int(float(res.group(4))*1000000),
'event':'function',
'callee' : res.group(5),
'caller' : res.group(6)
}
callback(Event(event))
continue
fid.close()
def get_partial_text(fn,start,end):
text = ""
fid = ftrace_open(fn)
linenumber = 0
for line in fid:
linenumber+=1
if linenumber >= start and linenumber <= end:
text+=line
return text
def load_ftrace(fn):
from timechart.model import tcProject
proj = tcProject()
proj.filename = fn
proj.start_parsing(get_partial_text)
parse_ftrace(fn,proj.handle_trace_event)
proj.finish_parsing()
return proj
def detect_ftrace(fn):
if fn.endswith(".txt"):
return load_ftrace
if fn.endswith(".txt.gz"):
return load_ftrace
if fn.endswith(".txt.lzma"):
return load_ftrace
return None
#### TEST ######################################################################
if __name__ == "__main__":
def callback(event):
#print event.__dict__
pass
parse_ftrace(sys.argv[1],callback)
#### EOF ######################################################################
|