Formatting user events with the System Profiler

Using the TraceEvent API, it's possible to emit custom trace events. However, these events are often difficult to understand in the Momentics IDE, since they don't have named fields the way QNX-provided events do. To address this, we've provided a mechanism for users to specify custom event formatted using an XML file. This guide provides an introduction to user event formatting so that you can interpret trace event data more effectively. The datakey specifier from the top-level eventdefinitons tag includes several subtags which are useful for formatting custom user events from the kernel. This data appears in the Trace Event Log table of the System Profiler. This guide covers the following subtags: event, bitmask, condition, and enum. For the XML reference, go to System Profiler: user event formatting XML reference.

Overview

You can upload an XML file with your user formatting using the Properties view of an open trace. To upload the file:
  1. Navigate to the Properties tab of an open trace.
  2. Click the Browse button to locate the file with your XML formatting.
System Profiler data format

Enums

It's useful to use an enum to match against a number of expected values.

Matching values directly:

For user (class 6) event 10, you could match against an enum as follows:

<eventdefinitions>
    <datakey format="%x mydata">
        <event class="6" id="10" />
        <enum name="mydata" value="0x0" string="zero"/>
        <enum name="mydata" value="0x1" string="one"/>
        <enum name="mydata" value="0x2" string="two"/>
        <enum name="mydata" value="0x3" string="three"/>
        <enum name="mydata" value="0x4" string="four"/>
        <enum name="mydata" value="0x5" string="five"/>
        <enum name="mydata" value="0x6" string="six"/>
        <enum name="mydata" value="0x7" string="seven"/>
    </datakey>
</eventdefinitions>

In this case, the enum takes the value of the mydata field, and does a simple equality check against the values provided. It displays the provided string on a match.

For example, if the mydata field is equal to 5, then the enum outputs the following:

Event Data:         mydata:0x5 five
Event Data Hex:     0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00

Matching values after applying a mask:

You can match values after applying a mask to read flags. For user (class 6) event 8, you can apply the following mask:

<eventdefinitions>
    <datakey format="%x mydata">
        <event class="6" id="8"/>
        <enum name="mydata" mask="0x00000001" string="MASK1" />
        <enum name="mydata" mask="0x00000002" string="MASK2" />
        <enum name="mydata" mask="0x00000004" string="MASK3" />
        <enum name="mydata" mask="0x00000003" string="MASK5" />
        <enum name="mydata" mask="0x00000008" string="MASK8" />
    </datakey>
</eventdefinitions>
            

An enum mask works by applying the mask to the value read from the field in the format string and checking to see if the masked value is equal to the mask.

For example, if the mydata field is equal to 5, then the enum outputs the following:

Event Data:         mydata:0x5 MASK1 MASK3
Event Data Hex:     0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00
            

Bitmasks and Enums

If multiple values are combined into a single value, then you can apply a bitmask and an enum to extract data.

For example, a bitmask and an enum are used to match against the lower 3 bits of a value. For user (class 6) event 10, you could apply a mask as follows:

<eventdefinitions>
    <datakey format="%x enum_bitmask">
        <event class="6" id="10" />
        <bitmask value="0x00000007" />
        <enum name="enum_bitmask" value="0x0" string="zero"/>
        <enum name="enum_bitmask" value="0x1" string="one"/>
        <enum name="enum_bitmask" value="0x2" string="two"/>
        <enum name="enum_bitmask" value="0x3" string="three"/>
        <enum name="enum_bitmask" value="0x4" string="four"/>
        <enum name="enum_bitmask" value="0x5" string="five"/>
        <enum name="enum_bitmask" value="0x6" string="six"/>
        <enum name="enum_bitmask" value="0x7" string="seven"/>
    </datakey>
</eventdefinitions>
            

In this case, you apply the bitmask first, changing the value of enum_bitmask. Then, you apply any regular enum matching logic. For example, if the mydata field is equal to 0xFFFFFFFF, then the formatting outputs the following:

Event Data:         enum_bitmask:0x7 seven
Event Data Hex:     0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
            

Additionally, since this datakey only contains a single element (enum_bitmask), the name attribute is not strictly required on the enum tags:

<eventdefinitions>
    <datakey format="%x enum_bitmask">
        <event class="6" id="10" />
        <bitmask value="0x00000007" />
        <enum value="0x0" string="zero"/>
        <enum value="0x1" string="one"/>
        <enum value="0x2" string="two"/>
        <enum value="0x3" string="three"/>
        <enum value="0x4" string="four"/>
        <enum value="0x5" string="five"/>
        <enum value="0x6" string="six"/>
        <enum value="0x7" string="seven"/>
    </datakey>
</eventdefinitions>
            

Conditions

Conditions are used to conditionally apply user event data formatting. For example, you can use conditions to display detailed error codes (when the status code is incorrect).

<eventdefinitions>
    <datakey format="%2s1d status %4u1x pid" offset="0" wide_offset="0" show_masked_value="false">
        <event class="6" id="12" />
        <enum name="status" value="0" string="OK" />
        <enum name="status" value="-1" string="Error" />
    </datakey>
    
    <datakey format="%4s1d error_no" offset="6">
        <event class="6" id="12" />
        <condition key="status" value="-1" />
        <enum name="error_no" value="1" string="EBADREQ" />
        <enum name="error_no" value="2" string="ENOWORKER" />
    </datakey>
</eventdefinitions>
            

The condition only applies if the status field is parsed as a negative value. If this is the case, then the condition adds the format error_no to the event data and applies the enum. For example:

Event Data:         status:-1 Error pid:0x7c5 error_no:1 EBADREQ
Event Data Hex:     0xFF 0xFF 0xC5 0x07 0x00 0x00 0x01 0x00
                    0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                    0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                    0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
            

The example uses offsets to specify where to find the error_no value. You specify the offset since you don't want to start at 0 (which is where the status field is encoded). The offset is an index into the array of event data. For example, you can find the error_no code by indexing the event hex data and reading 4 bytes at offset 6 (the size is specified by the format string).

Event Data Hex:
0    1    2    3    4    5    6    7
0xFF 0xFF 0xC5 0x07 0x00 0x00 0x01 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
            
Note:
The event data hex values are little endian in these examples. If you aren't familiar with little-endian encoding, then be aware that each piece of data might appear backwards. This is why the following set of bytes is interpreted as 1: 0x01 0x00 0x00 0x00.

Using a mask and value in a condition

You can combine a mask and a value in a condition, which is useful when you want to locate multiple fields within data.

For example, consider the following example; it masks the header element and, if the value matches 0 after the mask, then it applies additional formatting. You could use this to match against the lower two bits of header field encoded with a payload type.

<eventdefinitions>
    <datakey format="%4u1x id %4u1d size %1s0 data" offset="10">
        <event class="6" id="12"/>
        <condition name="header" mask="0x3" value="0"/>
    </datakey>
</eventdefinitions>
            

The above formatting results in the following output:

Event Data:         status:0 OK pid:0x7c5 header:0x4 BROADCAST id:0x9abccba9 size:14 data:exampleMessage
Event Data Hex:     0x00 0x00 0xC5 0x07 0x00 0x00 0x04 0x00
                    0x00 0x00 0xA9 0xCB 0xBC 0x9A 0x0E 0x00
                    0x00 0x00 0x65 0x78 0x61 0x6D 0x70 0x6C
                    0x65 0x4D 0x65 0x73 0x73 0x61 0x67 0x65
            

In the above example, the formatting is applied even though the header field's value is 0x4. The formatting applies because the 4 is masked out by the condition's mask and the resulting value is equal to the condition's value of 0.

You can provide a different format when the masked condition value is different:

    
<eventdefinitions>
    <datakey format="%4u1x id %4u1d size %1s0 data" offset="10">
        <event class="6" id="12"/>
        <condition name="header" mask="0x3" value="0"/>
    </datakey>
    
    <datakey format="%4u1x id %4u1x data" offset="10">
        <event class="6" id="12"/>
        <condition key="header" mask="0x3" value="1"/>
    </datakey>
</eventdefinitions>
            

In this case, only the id and data fields are applied since the header is masked and the value equals 1 instead of 0:

                
Event Data:         status:0 OK pid:0x7c5 header:0x1 id:0xbeefbeef data:18
Event Data Hex:     0x00 0x00 0xC5 0x07 0x00 0x00 0x01 0x00
                    0x00 0x00 0xEF 0xBE 0xEF 0xBE 0x12 0x00
                    0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
                    0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
            
Note:
The difference between the formats in the example is related to whether or not the size field is parsed from the data.
Page updated: