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