[lttng-dev] Reading CTF trace using Babeltrace API

Jérémie Galarneau jeremie.galarneau at efficios.com
Tue Oct 8 14:52:38 EDT 2013


On Mon, Oct 7, 2013 at 11:54 AM, Salman Rafiq
<salman.rafiq at esk.fraunhofer.de> wrote:
> Hi Jérémie,
>
> Thanks for your prompt reply.
>
>
> Just to add a little to your answer:
>
> In order to get the event "id" field, we need to call another function as well.
> Since the "id" field is declared as an enumerated data type (uint16_t for large header and uint5_t for compact).
> For example, to read the event id, it works only by calling bt_ctf_get_enum_int(id_field), otherwise it returns 0.
>

Absolutely. I was testing this on a sample trace that didn't have the
same event_header declaration. But for traces currently generated by
the tracers, this is correct. Thanks for clarifying.

> Slight modification to the code sample did the job:
>
> while ((ctf_event = bt_ctf_iter_read_event(iter))) {
>
>         const struct bt_definition *stream_event_header_scope =
>                 bt_ctf_get_top_level_scope(
>                         ctf_event, BT_STREAM_EVENT_HEADER);
>         const struct bt_definition *id_field =
>                 bt_ctf_get_field(
>                         ctf_event, stream_event_header_scope, "id");
>
>         printf("id = %" PRIu64 "\n", bt_ctf_get_uint64(bt_ctf_get_enum_int(id_field)));         // change here!!!
>
>
>
> But I am getting strange behavior only for the "sched_switch" event.
> Each time I read it, it returns 31 in case the header is compact (31 events max) and 65535 when the header is large instead of the correct value.
>
> For all other "id's" of the event, it returns correct value :-s
>
> I am unable to figure out the reason. Please let me know, if you have any information in this regard.

The problem is that the "id" fields in both struct
event_header_compact and event_header_large acts as a variant's tag
enumeration.

For instance, if we take a look at the event_header_compact structure,

struct event_header_compact {
        enum : uint5_t { compact = 0 ... 30, extended = 31 } id;
        variant <id> {
                struct {
                        uint27_clock_monotonic_t timestamp;
                } compact;
                struct {
                        uint32_t id;
                        uint64_clock_monotonic_t timestamp;
                } extended;
        } v;
} align(8);

The "enum id" field will indicate the event's id if it has a value of
[0, 30]. It also indicates that the "compact" structure is selected in
the variant that follows. If id == 31, the "extended" structure is
selected, which means that you should retrieve the "id" field's value
from that structure.

Since code is worth a thousand words, here's a more complete code
sample to read the id fields.

while ((ctf_event = bt_ctf_iter_read_event(iter))) {
        uint64_t event_id = 0;
        const struct bt_definition *stream_event_header_scope =
                bt_ctf_get_top_level_scope(
                        ctf_event, BT_STREAM_EVENT_HEADER);
        const struct bt_definition *id_definition =
                bt_ctf_get_field(ctf_event, stream_event_header_scope,
                                 "id");
        const struct bt_definition *v_definition =
                bt_ctf_get_field(ctf_event, stream_event_header_scope,
                                 "v");

        /* "id may be an enum, get the underlying integer if it's the case */
        if (id_definition &&
bt_ctf_field_type(bt_ctf_get_decl_from_def(id_definition)) ==
CTF_TYPE_ENUM) {
                id_definition = bt_ctf_get_enum_int(id_definition);
        }

        /* Check if there is a "v" field and if it contains an "id" field */
        if (v_definition &&
bt_ctf_field_type(bt_ctf_get_decl_from_def(v_definition)) ==
CTF_TYPE_STRUCT) {
                struct bt_definition const * const *list = NULL;
                unsigned int count = 0;
                unsigned int i;

                ret = bt_ctf_get_field_list(ctf_event, v_definition,
&list, &count);
                if (ret) {
                        goto end;
                }

                for (i = 0; i < count; i++) {
                        const char *name = bt_ctf_field_name(list[i]);

                        if (strcmp("id", name) == 0) {
                                id_definition = list[i];
                                break;
                        }
                }
        }

        if (id_definition &&
bt_ctf_field_type(bt_ctf_get_decl_from_def(id_definition)) ==
CTF_TYPE_INTEGER) {
                event_id = bt_ctf_get_uint64(id_definition);
        }

        printf("id = %" PRIu64 "\n", event_id);
}

Regards,
Jérémie

> Thanks a lot!
>
> Regards,
> Salman
>
> --
> Salman Rafiq
> Geschäftsfeld Industrial Communication
> Fraunhofer-Institut  für Eingebettete Systeme und Kommunikationstechnik ESK
>
> Hansastraße 32 | 80686 München
> Telefon, Fax:  +49 89 547088-356 | +49 89 547088-221
> E-Mail:   salman.rafiq at esk.fraunhofer.de
>
> Internet:
> http://www.esk.fraunhofer.de
> http://www.twitter.com/FraunhoferESK
>
>
> -----Original Message-----
> From: jeremie.galarneau at gmail.com [mailto:jeremie.galarneau at gmail.com] On Behalf Of Jérémie Galarneau
> Sent: Mittwoch, 2. Oktober 2013 20:25
> To: Salman Rafiq
> Cc: jdesfossez at efficios.com; lttng-dev at lists.lttng.org; Mathieu Desnoyers
> Subject: Re: Reading CTF trace using Babeltrace API
>
> On Wed, Oct 2, 2013 at 12:55 PM, Salman Rafiq <salman.rafiq at esk.fraunhofer.de> wrote:
>> Dear LTTngers,
>>
>> I would like to ask few questions related to the API's for reading CTF traces.
>>
>> 1.  Is there any way to read CTF metadata independently, like we have certain API's to read the events.
>>
>
> Not from the public API, unfortunately.
>
>> 2. There are certain scopes defined in ctf/events.h like:
>>         BT_TRACE_PACKET_HEADER          = 0,
>>         BT_STREAM_PACKET_CONTEXT        = 1,
>>         BT_STREAM_EVENT_HEADER          = 2,
>>         BT_STREAM_EVENT_CONTEXT         = 3,
>>         BT_EVENT_CONTEXT                = 4,
>>         BT_EVENT_FIELDS                 = 5,
>>
>> I could not figure out the way to ready the fields 'id' and 'stream_id', for a particular event while iterating through the trace.
>> Though I can ready the event name using an API and fields using BT_EVENT_FIELDS as a scope.
>> For e.g. consider the
>>
>> event {
>>         name = sched_migrate_task;
>>         id = 1;
>>         stream_id = 0;
>>         fields := struct {
>>                 integer { size = 8; align = 8; signed = 1; encoding = UTF8; base = 10; } _comm[16];
>>                 integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _tid;
>>                 integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _prio;
>>                 integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _orig_cpu;
>>                 integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _dest_cpu;
>>         };
>> };
>>
>
> The "id" field is part of the BT_STREAM_EVENT_HEADER scope, while the "stream_id" field is part of the BT_TRACE_PACKET_HEADER scope.
>
> The code below is adapted from converter/babeltrace.c's
> convert_trace() loop to print both values.
>
> while ((ctf_event = bt_ctf_iter_read_event(iter))) {
>
>         const struct bt_definition *stream_event_header_scope =
>                 bt_ctf_get_top_level_scope(
>                         ctf_event, BT_STREAM_EVENT_HEADER);
>         const struct bt_definition *id_field =
>                 bt_ctf_get_field(
>                         ctf_event, stream_event_header_scope, "id");
>
>         printf("id = %" PRIu64 "\n", bt_ctf_get_uint64(id_field));
>
>         const struct bt_definition *packet_header_scope =
>                 bt_ctf_get_top_level_scope(
>                         ctf_event, BT_TRACE_PACKET_HEADER);
>         const struct bt_definition *stream_id_field =
>                 bt_ctf_get_field(
>                         ctf_event, packet_header_scope, "stream_id");
>
>         printf("stream_id = %" PRIu64 "\n", bt_ctf_get_uint64(
>                        stream_id_field)); [...] }
>
> Regards,
> Jérémie
>
>>
>> Any help or suggestion related to this issue will be really appreciated.
>> Thanks!
>>
>> Regards,
>> Salman
>>
>> --
>> Salman Rafiq
>> Geschäftsfeld Industrial Communication Fraunhofer-Institut  für
>> Eingebettete Systeme und Kommunikationstechnik ESK
>>
>> Hansastraße 32 | 80686 München
>> Telefon, Fax:  +49 89 547088-356 | +49 89 547088-221
>> E-Mail:   salman.rafiq at esk.fraunhofer.de
>>
>> Internet:
>> http://www.esk.fraunhofer.de
>> http://www.twitter.com/FraunhoferESK
>>
>
>
>
> --
> Jérémie Galarneau
> EfficiOS Inc.
> http://www.efficios.com



-- 
Jérémie Galarneau
EfficiOS Inc.
http://www.efficios.com



More information about the lttng-dev mailing list