| 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) |
| ) |
| --- >% --- |