128 lines
3.5 KiB
Plaintext
128 lines
3.5 KiB
Plaintext
PYTHON PLUGIN DOCUMENTATION
|
|
=============================
|
|
|
|
With the python plugin (make python-plugin) you can now
|
|
write plugins in python. The API exported by the python
|
|
plugin itself (written in C) allows you to access most
|
|
information about a record from python.
|
|
|
|
To write a python plugin, put a new .py file into a new
|
|
~/.trace-cmd/python/ directory.
|
|
|
|
The most basic python plugin is this:
|
|
|
|
--- %< ---
|
|
def register(pevent):
|
|
pass
|
|
--- >% ---
|
|
|
|
which obviously does nothing at all.
|
|
|
|
To register a callback, use the pevent.register_event_handler
|
|
function:
|
|
|
|
--- %< ---
|
|
import tracecmd
|
|
|
|
def my_event_handler(trace_seq, event):
|
|
pass
|
|
|
|
def register(pevent):
|
|
pevent.register_event_handler("subsys", "event_name",
|
|
my_event_handler)
|
|
--- >% ---
|
|
|
|
|
|
There are four object types that you get, described below.
|
|
|
|
tracecmd.PEvent
|
|
-----------------
|
|
|
|
This is the class of the 'pevent' object above,
|
|
you get one of those via your register callback.
|
|
It has one method and one property:
|
|
* register_event_handler() - example above, to register
|
|
an event handler function
|
|
* file_endian - either '<' or '>' indicating
|
|
which endianness the file has,
|
|
to be used with struct.unpack()
|
|
|
|
tracecmd.TraceSeq
|
|
-------------------
|
|
|
|
This is the class of the 'trace_seq' parameter to your callback
|
|
function. It has only one method, puts(), to put data into the
|
|
buffer. Formatting must be done in python.
|
|
|
|
tracecmd.Event
|
|
----------------------
|
|
|
|
This is the class of the 'event' parameter to your callback
|
|
function. Note that it doesn't just contain the format, but
|
|
also the event data. As such, you can do much with this, and
|
|
this is what you'll usually use. Each instance of this allows
|
|
access to record items via the dict protocol, and you can get
|
|
the items via its keys() methods. So for example, your
|
|
callback could be
|
|
|
|
--- %< ---
|
|
def my_callback(trace_seq, event):
|
|
for fieldname in event.keys():
|
|
field = event[fieldname]
|
|
--- >% ---
|
|
|
|
Each field returned from the dict protocol is an instance of
|
|
the next (and last) class:
|
|
|
|
tracecmd.Field
|
|
----------------------
|
|
|
|
This is an instance of a field, including its data. It affords
|
|
numerous use cases and is what you'll be using most.
|
|
|
|
* If this is an integer field, i.e. 1, 2, 4 or 8 bytes long,
|
|
you can convert it to the number contained, according to
|
|
the file's endianness, by simply casting it to a long:
|
|
|
|
field = event['myint']
|
|
value = long(field)
|
|
|
|
* You can access the field's data, as field.data, and if the
|
|
data is really a "__data_loc" type that will be resolved
|
|
automatically. (If you don't know what this means, don't
|
|
worry about it and just use field.data)
|
|
|
|
|
|
This is it. It's pretty simple. A fully-featured plugin could
|
|
look like this:
|
|
|
|
--- %< ---
|
|
def my_event_handler(trace_seq, event):
|
|
trace_seq.puts("myev: %u", long(event['myfield']))
|
|
|
|
def register(pevent):
|
|
pevent.register_event_handler("subsys", "event_name",
|
|
my_event_handler)
|
|
--- >% ---
|
|
|
|
|
|
Tips and tricks
|
|
-----------------
|
|
|
|
Be familiar with the struct module and use it, always
|
|
checking endianness and potentially using pevent.file_endian.
|
|
|
|
|
|
If you need access to pevent in your callbacks, simply
|
|
pass it in yourself:
|
|
|
|
--- %< ---
|
|
def my_event_handler(pevent, trace_seq, event):
|
|
pass
|
|
|
|
def register(pevent):
|
|
pevent.register_event_handler("subsys", "event_name",
|
|
lambda *args: my_event_handler(pevent, *args)
|
|
)
|
|
--- >% ---
|