diff options
Diffstat (limited to 'tracecmd.py')
-rw-r--r-- | tracecmd.py | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/tracecmd.py b/tracecmd.py new file mode 100644 index 0000000..6520a48 --- /dev/null +++ b/tracecmd.py | |||
@@ -0,0 +1,135 @@ | |||
1 | # | ||
2 | # Copyright (C) International Business Machines Corp., 2009 | ||
3 | # | ||
4 | # This program is free software; you can redistribute it and/or modify | ||
5 | # it under the terms of the GNU General Public License as published by | ||
6 | # the Free Software Foundation; either version 2 of the License, or | ||
7 | # (at your option) any later version. | ||
8 | # | ||
9 | # This program is distributed in the hope that it will be useful, | ||
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | # GNU General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with this program; if not, write to the Free Software | ||
16 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
17 | # | ||
18 | # 2009-Dec-17: Initial version by Darren Hart <dvhltc@us.ibm.com> | ||
19 | # | ||
20 | |||
21 | from ctracecmd import * | ||
22 | |||
23 | """ | ||
24 | Python interface to the tracecmd library for parsing ftrace traces | ||
25 | |||
26 | Python tracecmd applications should be written to this interface. It will be | ||
27 | updated as the tracecmd C API changes and try to minimze the impact to python | ||
28 | applications. The ctracecmd Python module is automatically generated using SWIG | ||
29 | and it is recommended applications not use it directly. | ||
30 | |||
31 | TODO: consider a complete class hierarchy of ftrace events... | ||
32 | """ | ||
33 | |||
34 | def _pevent_read_number_field(field, data): | ||
35 | ret,hi,lo = pevent_read_number_field_32(field, data) | ||
36 | if ret == 0: | ||
37 | return ret,long(long(hi).__lshift__(32)+lo) | ||
38 | return ret,None | ||
39 | |||
40 | |||
41 | class Event(object): | ||
42 | def __init__(self, trace, record): | ||
43 | self.trace = trace | ||
44 | self.rec = record | ||
45 | type = pevent_data_type(trace.pe, record) | ||
46 | self.ec = pevent_data_event_from_type(trace.pe, type) | ||
47 | |||
48 | def __str__(self): | ||
49 | return "%f %s: pid=%d comm=%s type=%d" % \ | ||
50 | (self.ts, self.name, self.num_field("common_pid"), self.comm, self.type) | ||
51 | |||
52 | |||
53 | # TODO: consider caching the results of the properties | ||
54 | @property | ||
55 | def comm(self): | ||
56 | return self.trace.comm_from_pid(self.pid) | ||
57 | |||
58 | @property | ||
59 | def name(self): | ||
60 | return event_name_get(self.ec) | ||
61 | |||
62 | @property | ||
63 | def pid(self): | ||
64 | return pevent_data_pid(self.trace.pe, self.rec) | ||
65 | |||
66 | @property | ||
67 | def ts(self): | ||
68 | # FIXME: this currently returns a float instead of a 64bit nsec value | ||
69 | return record_ts_get(self.rec) | ||
70 | |||
71 | @property | ||
72 | def type(self): | ||
73 | return pevent_data_type(self.trace.pe, self.rec) | ||
74 | |||
75 | def num_field(self, name): | ||
76 | # FIXME: need to find an elegant way to handle 64bit fields | ||
77 | f = pevent_find_any_field(self.ec, name) | ||
78 | ret,val = _pevent_read_number_field(f, record_data_get(self.rec)) | ||
79 | return val | ||
80 | |||
81 | |||
82 | class Trace(object): | ||
83 | """ | ||
84 | Trace object represents the trace file it is created with. | ||
85 | |||
86 | The Trace object aggregates the tracecmd structures and functions that are | ||
87 | used to manage the trace and extract events from it. | ||
88 | """ | ||
89 | def __init__(self, filename): | ||
90 | self.handle = None | ||
91 | self.pe = None | ||
92 | |||
93 | try: | ||
94 | file = open(filename) | ||
95 | self.handle = tracecmd_open(file.fileno()) | ||
96 | print "self.handle: ", self.handle | ||
97 | #FIXME: check if these throw exceptions automatically or if we have | ||
98 | # to check return codes manually | ||
99 | tracecmd_read_headers(self.handle) | ||
100 | tracecmd_init_data(self.handle) | ||
101 | self.pe = tracecmd_get_pevent(self.handle) | ||
102 | except: | ||
103 | return None | ||
104 | |||
105 | @property | ||
106 | def cpus(self): | ||
107 | return tracecmd_cpus(self.handle) | ||
108 | |||
109 | def read_event(self, cpu): | ||
110 | rec = tracecmd_read_data(self.handle, cpu) | ||
111 | if rec: | ||
112 | return Event(self, rec) | ||
113 | return None | ||
114 | |||
115 | def peek_event(self, cpu): | ||
116 | pass | ||
117 | |||
118 | def comm_from_pid(self, pid): | ||
119 | return pevent_data_comm_from_pid(self.pe, pid) | ||
120 | |||
121 | |||
122 | # Basic builtin test, execute module directly | ||
123 | if __name__ == "__main__": | ||
124 | t = Trace("trace.dat") | ||
125 | print "Trace contains data for %d cpus" % (t.cpus) | ||
126 | |||
127 | for cpu in range(0, t.cpus): | ||
128 | print "CPU %d" % (cpu) | ||
129 | ev = t.read_event(cpu) | ||
130 | while ev: | ||
131 | print "\t%s" % (ev) | ||
132 | ev = t.read_event(cpu) | ||
133 | |||
134 | |||
135 | |||