Commit | Line | Data |
---|---|---|
4f5f37d9 PP |
1 | .. _examples: |
2 | ||
3 | ******** | |
4 | Examples | |
5 | ******** | |
6 | ||
7 | This section presents a few short and straightforward examples | |
4e5f388f | 8 | of Babeltrace legacy Python bindings usage. |
4f5f37d9 PP |
9 | |
10 | The examples are divided into two categories: those which demonstrate | |
11 | the :ref:`reader API <reader-api>`, and those which demonstrate | |
12 | the :ref:`CTF writer API <ctf-writer-api>`. | |
13 | ||
14 | ||
15 | .. _reader-api-examples: | |
16 | ||
17 | Reader API examples | |
18 | =================== | |
19 | ||
20 | The :ref:`reader API <reader-api>` includes everything needed to open | |
21 | traces and iterate on events in order. | |
22 | ||
23 | ||
24 | Open one trace and print all event names | |
25 | ---------------------------------------- | |
26 | ||
27 | This example shows how to open a single CTF trace, iterate on all the | |
28 | events, and print their names. | |
29 | ||
30 | .. code-block:: python | |
31 | ||
32 | import babeltrace.reader | |
33 | import sys | |
34 | ||
35 | ||
36 | # get the trace path from the first command line argument | |
37 | trace_path = sys.argv[1] | |
38 | ||
39 | trace_collection = babeltrace.reader.TraceCollection() | |
40 | ||
41 | trace_collection.add_trace(trace_path, 'ctf') | |
42 | ||
43 | for event in trace_collection.events: | |
44 | print(event.name) | |
45 | ||
46 | ||
47 | Open multiple traces and print all event field names | |
48 | ---------------------------------------------------- | |
49 | ||
50 | This example opens multiple CTF traces (their paths are provided as | |
51 | command line arguments), iterates on all their correlated events in | |
52 | order, and prints a list of their field names. | |
53 | ||
54 | .. code-block:: python | |
55 | ||
56 | import babeltrace.reader | |
57 | import sys | |
58 | ||
59 | ||
60 | trace_collection = babeltrace.reader.TraceCollection() | |
61 | ||
62 | for path in sys.argv[1:]: | |
63 | trace_collection.add_trace(path, 'ctf') | |
64 | ||
65 | for event in trace_collection.events: | |
66 | print(', '.join(event.keys())) | |
67 | ||
68 | ||
69 | Print a specific event field | |
70 | ---------------------------- | |
71 | ||
72 | Reading the field value of an :class:`babeltrace.reader.Event` object | |
73 | is done by using its :class:`dict`-like interface: | |
74 | ||
75 | .. code-block:: python | |
76 | ||
77 | field_value = event['field_name'] | |
78 | ||
79 | As such, you can use Python's ``in`` keyword to verify if a given | |
80 | event contains a given field name: | |
81 | ||
82 | .. code-block:: python | |
83 | ||
84 | if 'field_name' in event: | |
85 | # ... | |
86 | ||
87 | The following example iterates on the events of a trace, and prints the | |
88 | value of the ``fd`` field if it's available. | |
89 | ||
90 | .. code-block:: python | |
91 | ||
92 | import babeltrace.reader | |
93 | import sys | |
94 | ||
95 | # get the trace path from the first command line argument | |
96 | trace_path = sys.argv[1] | |
97 | ||
98 | trace_collection = babeltrace.reader.TraceCollection() | |
99 | ||
100 | trace_collection.add_trace(trace_path, 'ctf') | |
101 | ||
102 | for event in trace_collection.events: | |
103 | if 'fd' in event: | |
104 | print(event['fd']) | |
105 | ||
106 | Beware that different fields of the same event may share the same name | |
107 | if they are in different scopes. In this case, the :class:`dict`-like | |
108 | interface prioritizes event payload fields before event context fields, | |
109 | event context fields before stream event context fields, and so on | |
110 | (see :class:`babeltrace.reader.Event` for this exact list of | |
111 | priorities). It is possible to get the value of an event's field | |
112 | within a specific scope using | |
113 | :meth:`babeltrace.reader.Event.field_with_scope`: | |
114 | ||
115 | .. code-block:: python | |
116 | ||
117 | import babeltrace.reader | |
118 | import babeltrace.common | |
119 | ||
120 | # ... | |
121 | ||
122 | field_value = event.field_with_scope('field_name', | |
123 | babeltrace.common.CTFScope.EVENT_CONTEXT) | |
124 | ||
125 | ||
126 | Bonus: top 5 running processes using LTTng | |
127 | ------------------------------------------ | |
128 | ||
129 | Since `LTTng <http://lttng.org/>`_ produces CTF traces, the | |
130 | Babeltrace Python binding can read LTTng traces. | |
131 | ||
132 | This somewhat more complex example reads a whole LTTng Linux kernel | |
133 | trace, and outputs the short names of the top 5 running processes on | |
134 | CPU 0 during the whole trace. | |
135 | ||
136 | .. code-block:: python | |
137 | ||
138 | from collections import Counter | |
139 | import babeltrace.reader | |
140 | import sys | |
141 | ||
142 | ||
143 | # a trace collection holds one or more traces | |
144 | col = babeltrace.reader.TraceCollection() | |
145 | ||
146 | # add the trace provided by the user (first command line argument) | |
147 | # (LTTng traces always have the 'ctf' format) | |
148 | if col.add_trace(sys.argv[1], 'ctf') is None: | |
149 | raise RuntimeError('Cannot add trace') | |
150 | ||
151 | # this counter dict will hold execution times: | |
152 | # | |
153 | # task command name -> total execution time (ns) | |
154 | exec_times = Counter() | |
155 | ||
156 | # this holds the last `sched_switch` timestamp | |
157 | last_ts = None | |
158 | ||
159 | # iterate on events | |
160 | for event in col.events: | |
161 | # keep only `sched_switch` events | |
162 | if event.name != 'sched_switch': | |
163 | continue | |
164 | ||
165 | # keep only events which happened on CPU 0 | |
166 | if event['cpu_id'] != 0: | |
167 | continue | |
168 | ||
169 | # event timestamp | |
170 | cur_ts = event.timestamp | |
171 | ||
172 | if last_ts is None: | |
173 | # we start here | |
174 | last_ts = cur_ts | |
175 | ||
176 | # previous task command (short) name | |
177 | prev_comm = event['prev_comm'] | |
178 | ||
179 | # initialize entry in our dict if not yet done | |
180 | if prev_comm not in exec_times: | |
181 | exec_times[prev_comm] = 0 | |
182 | ||
183 | # compute previous command execution time | |
184 | diff = cur_ts - last_ts | |
185 | ||
186 | # update execution time of this command | |
187 | exec_times[prev_comm] += diff | |
188 | ||
189 | # update last timestamp | |
190 | last_ts = cur_ts | |
191 | ||
192 | # print top 5 | |
193 | for name, ns in exec_times.most_common(5): | |
194 | s = ns / 1000000000 | |
195 | print('{:20}{} s'.format(name, s)) | |
196 | ||
197 | ||
198 | Inspect event declarations and their field declarations | |
199 | ------------------------------------------------------- | |
200 | ||
201 | When :meth:`babeltrace.reader.TraceCollection.add_trace` is called | |
202 | and a trace is successfully opened and added, a corresponding | |
203 | :class:`babeltrace.reader.TraceHandle` object for this trace is | |
204 | returned. It is then possible to iterate on the event declarations of | |
205 | this trace handle using :attr:`babeltrace.reader.TraceHandle.events`. | |
206 | Each generated :class:`babeltrace.reader.EventDeclaration` object | |
207 | contains common properties for this type of event, including its | |
208 | field declarations. This is useful for inspecting the available | |
209 | events of a trace, and their "signature" in terms of fields, before | |
210 | iterating its actual events. | |
211 | ||
212 | This example adds a trace to a trace collection, and uses the returned | |
213 | trace handle to iterate on its event declarations. The goal here is to | |
214 | make sure the ``sched_switch`` event exists, and that it contains | |
215 | at least the following fields: | |
216 | ||
217 | * ``prev_comm``, which should be an array of 8-bit integers | |
218 | * ``prev_tid``, which should be an integer | |
219 | ||
220 | .. code-block:: python | |
221 | ||
222 | import babeltrace.reader as btr | |
223 | import sys | |
224 | ||
225 | ||
226 | def validate_sched_switch_fields(event_decl): | |
227 | found_prev_comm = False | |
228 | found_prev_tid = False | |
229 | ||
230 | for field_decl in event_decl.fields: | |
231 | if field_decl.name == 'prev_comm': | |
232 | if isinstance(field_decl, btr.ArrayFieldDeclaration): | |
233 | elem_decl = field_decl.element_declaration | |
234 | ||
235 | if isinstance(elem_decl, btr.IntegerFieldDeclaration): | |
236 | if elem_decl.size == 8: | |
237 | found_prev_comm = True | |
238 | elif field_decl.name == 'prev_tid': | |
239 | if isinstance(field_decl, btr.IntegerFieldDeclaration): | |
240 | found_prev_tid = True | |
241 | ||
242 | return found_prev_comm and found_prev_tid | |
243 | ||
244 | ||
245 | # get the trace path from the first command line argument | |
246 | trace_path = sys.argv[1] | |
247 | ||
248 | trace_collection = btr.TraceCollection() | |
249 | trace_handle = trace_collection.add_trace(trace_path, 'ctf') | |
250 | sched_switch_found = False | |
251 | ||
252 | for event_decl in trace_handle.events: | |
253 | if event_decl.name == 'sched_switch': | |
254 | if validate_sched_switch_fields(event_decl): | |
255 | sched_switch_found = True | |
256 | break | |
257 | ||
258 | print('trace path: {}'.format(trace_handle.path)) | |
259 | ||
260 | if sched_switch_found: | |
261 | print('found sched_switch!') | |
262 | else: | |
263 | print('could not find sched_switch') | |
264 | ||
265 | ||
266 | .. _ctf-writer-api-examples: | |
267 | ||
268 | CTF writer API examples | |
269 | ======================= | |
270 | ||
271 | The :ref:`CTF writer API <ctf-writer-api>` is a set of classes which | |
272 | allows a Python script to write complete | |
273 | `CTF <http://www.efficios.com/ctf>`_ (Common Trace Format) traces. | |
274 | ||
275 | ||
276 | One trace, one stream, one event, one field | |
277 | ------------------------------------------- | |
278 | ||
279 | This is the most simple example of using the CTF writer API. It creates | |
280 | one writer (responsible for writing one trace), then uses it to create | |
281 | one stream. One event with a single field is appended to this single | |
282 | stream, and everything is flushed. | |
283 | ||
284 | The trace is written in a temporary directory (its path is printed | |
285 | at the beginning of the script). | |
286 | ||
287 | .. code-block:: python | |
288 | ||
289 | import babeltrace.writer as btw | |
290 | import tempfile | |
291 | ||
292 | ||
293 | # temporary directory holding the CTF trace | |
294 | trace_path = tempfile.mkdtemp() | |
295 | ||
296 | print('trace path: {}'.format(trace_path)) | |
297 | ||
298 | # our writer | |
299 | writer = btw.Writer(trace_path) | |
300 | ||
301 | # create one default clock and register it to the writer | |
302 | clock = btw.Clock('my_clock') | |
303 | clock.description = 'this is my clock' | |
304 | writer.add_clock(clock) | |
305 | ||
306 | # create one default stream class and assign our clock to it | |
307 | stream_class = btw.StreamClass('my_stream') | |
308 | stream_class.clock = clock | |
309 | ||
310 | # create one default event class | |
311 | event_class = btw.EventClass('my_event') | |
312 | ||
313 | # create one 32-bit signed integer field | |
314 | int32_field_decl = btw.IntegerFieldDeclaration(32) | |
315 | int32_field_decl.signed = True | |
316 | ||
317 | # add this field declaration to our event class | |
318 | event_class.add_field(int32_field_decl, 'my_field') | |
319 | ||
320 | # register our event class to our stream class | |
321 | stream_class.add_event_class(event_class) | |
322 | ||
323 | # create our single event, based on our event class | |
324 | event = btw.Event(event_class) | |
325 | ||
326 | # assign an integer value to our single field | |
327 | event.payload('my_field').value = -23 | |
328 | ||
329 | # create our single stream | |
330 | stream = writer.create_stream(stream_class) | |
331 | ||
332 | # append our single event to our single stream | |
333 | stream.append_event(event) | |
334 | ||
335 | # flush the stream | |
336 | stream.flush() | |
337 | ||
338 | ||
339 | Basic CTF fields | |
340 | ---------------- | |
341 | ||
342 | This example writes a few events with basic CTF fields: integers, | |
343 | floating point numbers, enumerations and strings. | |
344 | ||
345 | The trace is written in a temporary directory (its path is printed | |
346 | at the beginning of the script). | |
347 | ||
348 | .. code-block:: python | |
349 | ||
350 | import babeltrace.writer as btw | |
351 | import babeltrace.common | |
352 | import tempfile | |
353 | import math | |
354 | ||
355 | ||
356 | trace_path = tempfile.mkdtemp() | |
357 | ||
358 | print('trace path: {}'.format(trace_path)) | |
359 | ||
360 | ||
361 | writer = btw.Writer(trace_path) | |
362 | ||
363 | clock = btw.Clock('my_clock') | |
364 | clock.description = 'this is my clock' | |
365 | writer.add_clock(clock) | |
366 | ||
367 | stream_class = btw.StreamClass('my_stream') | |
368 | stream_class.clock = clock | |
369 | ||
370 | event_class = btw.EventClass('my_event') | |
371 | ||
372 | # 32-bit signed integer field declaration | |
373 | int32_field_decl = btw.IntegerFieldDeclaration(32) | |
374 | int32_field_decl.signed = True | |
375 | int32_field_decl.base = btw.IntegerBase.HEX | |
376 | ||
377 | # 5-bit unsigned integer field declaration | |
378 | uint5_field_decl = btw.IntegerFieldDeclaration(5) | |
379 | uint5_field_decl.signed = False | |
380 | ||
381 | # IEEE 754 single precision floating point number field declaration | |
382 | float_field_decl = btw.FloatingPointFieldDeclaration() | |
383 | float_field_decl.exponent_digits = btw.FloatingPointFieldDeclaration.FLT_EXP_DIG | |
384 | float_field_decl.mantissa_digits = btw.FloatingPointFieldDeclaration.FLT_MANT_DIG | |
385 | ||
386 | # enumeration field declaration (based on the 5-bit unsigned integer above) | |
387 | enum_field_decl = btw.EnumerationFieldDeclaration(uint5_field_decl) | |
388 | enum_field_decl.add_mapping('DAZED', 3, 11) | |
389 | enum_field_decl.add_mapping('AND', 13, 13) | |
390 | enum_field_decl.add_mapping('CONFUSED', 17, 30) | |
391 | ||
392 | # string field declaration | |
393 | string_field_decl = btw.StringFieldDeclaration() | |
394 | string_field_decl.encoding = babeltrace.common.CTFStringEncoding.UTF8 | |
395 | ||
396 | event_class.add_field(int32_field_decl, 'my_int32_field') | |
397 | event_class.add_field(uint5_field_decl, 'my_uint5_field') | |
398 | event_class.add_field(float_field_decl, 'my_float_field') | |
399 | event_class.add_field(enum_field_decl, 'my_enum_field') | |
400 | event_class.add_field(int32_field_decl, 'another_int32_field') | |
401 | event_class.add_field(string_field_decl, 'my_string_field') | |
402 | ||
403 | stream_class.add_event_class(event_class) | |
404 | ||
405 | stream = writer.create_stream(stream_class) | |
406 | ||
407 | # create and append first event | |
408 | event = btw.Event(event_class) | |
409 | event.payload('my_int32_field').value = 0xbeef | |
410 | event.payload('my_uint5_field').value = 17 | |
411 | event.payload('my_float_field').value = -math.pi | |
412 | event.payload('my_enum_field').value = 8 # label: 'DAZED' | |
413 | event.payload('another_int32_field').value = 0x20141210 | |
414 | event.payload('my_string_field').value = 'Hello, World!' | |
415 | stream.append_event(event) | |
416 | ||
417 | # create and append second event | |
418 | event = btw.Event(event_class) | |
419 | event.payload('my_int32_field').value = 0x12345678 | |
420 | event.payload('my_uint5_field').value = 31 | |
421 | event.payload('my_float_field').value = math.e | |
422 | event.payload('my_enum_field').value = 28 # label: 'CONFUSED' | |
423 | event.payload('another_int32_field').value = -1 | |
424 | event.payload('my_string_field').value = trace_path | |
425 | stream.append_event(event) | |
426 | ||
427 | stream.flush() | |
428 | ||
429 | ||
430 | Static array and sequence fields | |
431 | -------------------------------- | |
432 | ||
433 | This example demonstrates how to write static array and sequence | |
434 | fields. A static array has a fixed length, whereas a sequence reads | |
435 | its length dynamically from another (integer) field. | |
436 | ||
437 | In this example, an event is appended to a single stream, in which | |
438 | three fields are present: | |
439 | ||
440 | * ``seqlen``, the dynamic length of the sequence ``seq`` (set to the | |
441 | number of command line arguments) | |
442 | * ``array``, a static array of 23 16-bit unsigned integers | |
443 | * ``seq``, a sequence of ``seqlen`` strings, where the strings are | |
444 | the command line arguments | |
445 | ||
446 | The trace is written in a temporary directory (its path is printed | |
447 | at the beginning of the script). | |
448 | ||
449 | .. code-block:: python | |
450 | ||
451 | import babeltrace.writer as btw | |
452 | import babeltrace.common | |
453 | import tempfile | |
454 | import sys | |
455 | ||
456 | ||
457 | trace_path = tempfile.mkdtemp() | |
458 | ||
459 | print('trace path: {}'.format(trace_path)) | |
460 | ||
461 | ||
462 | writer = btw.Writer(trace_path) | |
463 | ||
464 | clock = btw.Clock('my_clock') | |
465 | clock.description = 'this is my clock' | |
466 | writer.add_clock(clock) | |
467 | ||
468 | stream_class = btw.StreamClass('my_stream') | |
469 | stream_class.clock = clock | |
470 | ||
471 | event_class = btw.EventClass('my_event') | |
472 | ||
473 | # 16-bit unsigned integer field declaration | |
474 | uint16_field_decl = btw.IntegerFieldDeclaration(16) | |
475 | uint16_field_decl.signed = False | |
476 | ||
477 | # array field declaration (23 16-bit unsigned integers) | |
478 | array_field_decl = btw.ArrayFieldDeclaration(uint16_field_decl, 23) | |
479 | ||
480 | # string field declaration | |
481 | string_field_decl = btw.StringFieldDeclaration() | |
482 | string_field_decl.encoding = babeltrace.common.CTFStringEncoding.UTF8 | |
483 | ||
484 | # sequence field declaration of strings (length will be the `seqlen` field) | |
485 | seq_field_decl = btw.SequenceFieldDeclaration(string_field_decl, 'seqlen') | |
486 | ||
487 | event_class.add_field(uint16_field_decl, 'seqlen') | |
488 | event_class.add_field(array_field_decl, 'array') | |
489 | event_class.add_field(seq_field_decl, 'seq') | |
490 | ||
491 | stream_class.add_event_class(event_class) | |
492 | ||
493 | stream = writer.create_stream(stream_class) | |
494 | ||
495 | # create event | |
496 | event = btw.Event(event_class) | |
497 | ||
498 | # set sequence length field | |
499 | event.payload('seqlen').value = len(sys.argv) | |
500 | ||
501 | # get array field | |
502 | array_field = event.payload('array') | |
503 | ||
504 | # populate array field | |
505 | for i in range(array_field_decl.length): | |
506 | array_field.field(i).value = i * i | |
507 | ||
508 | # get sequence field | |
509 | seq_field = event.payload('seq') | |
510 | ||
511 | # assign sequence field's length field | |
512 | seq_field.length = event.payload('seqlen') | |
513 | ||
514 | # populate sequence field | |
515 | for i in range(seq_field.length.value): | |
516 | seq_field.field(i).value = sys.argv[i] | |
517 | ||
518 | # append event | |
519 | stream.append_event(event) | |
520 | ||
521 | stream.flush() | |
522 | ||
523 | ||
524 | Structure fields | |
525 | ---------------- | |
526 | ||
527 | A CTF structure is an ordered map of field names to actual fields, just | |
528 | like C structures. In fact, an event's payload is a structure field, | |
529 | so structure fields may contain other structure fields, and so on. | |
530 | ||
531 | This examples shows how to create a structure field from a structure | |
532 | field declaration, populate it, and write an event containing it as | |
533 | a payload field. | |
534 | ||
535 | The trace is written in a temporary directory (its path is printed | |
536 | at the beginning of the script). | |
537 | ||
538 | .. code-block:: python | |
539 | ||
540 | import babeltrace.writer as btw | |
541 | import babeltrace.common | |
542 | import tempfile | |
543 | ||
544 | ||
545 | trace_path = tempfile.mkdtemp() | |
546 | ||
547 | print('trace path: {}'.format(trace_path)) | |
548 | ||
549 | ||
550 | writer = btw.Writer(trace_path) | |
551 | ||
552 | clock = btw.Clock('my_clock') | |
553 | clock.description = 'this is my clock' | |
554 | writer.add_clock(clock) | |
555 | ||
556 | stream_class = btw.StreamClass('my_stream') | |
557 | stream_class.clock = clock | |
558 | ||
559 | event_class = btw.EventClass('my_event') | |
560 | ||
561 | # 32-bit signed integer field declaration | |
562 | int32_field_decl = btw.IntegerFieldDeclaration(32) | |
563 | int32_field_decl.signed = True | |
564 | ||
565 | # string field declaration | |
566 | string_field_decl = btw.StringFieldDeclaration() | |
567 | string_field_decl.encoding = babeltrace.common.CTFStringEncoding.UTF8 | |
568 | ||
569 | # structure field declaration | |
570 | struct_field_decl = btw.StructureFieldDeclaration() | |
571 | ||
572 | # add field declarations to our structure field declaration | |
573 | struct_field_decl.add_field(int32_field_decl, 'field_one') | |
574 | struct_field_decl.add_field(string_field_decl, 'field_two') | |
575 | struct_field_decl.add_field(int32_field_decl, 'field_three') | |
576 | ||
577 | event_class.add_field(struct_field_decl, 'my_struct') | |
578 | event_class.add_field(string_field_decl, 'my_string') | |
579 | ||
580 | stream_class.add_event_class(event_class) | |
581 | ||
582 | stream = writer.create_stream(stream_class) | |
583 | ||
584 | # create event | |
585 | event = btw.Event(event_class) | |
586 | ||
587 | # get event's structure field | |
588 | struct_field = event.payload('my_struct') | |
589 | ||
590 | # populate this structure field | |
591 | struct_field.field('field_one').value = 23 | |
592 | struct_field.field('field_two').value = 'Achilles Last Stand' | |
593 | struct_field.field('field_three').value = -1534 | |
594 | ||
595 | # set event's string field | |
596 | event.payload('my_string').value = 'Tangerine' | |
597 | ||
598 | # append event | |
599 | stream.append_event(event) | |
600 | ||
601 | stream.flush() | |
602 | ||
603 | ||
604 | Variant fields | |
605 | -------------- | |
606 | ||
607 | The CTF variant is the most versatile field type. It acts as a | |
608 | placeholder for any other type. Which type is selected depends on the | |
609 | current value of an outer enumeration field, known as a *tag* from the | |
610 | variant's point of view. | |
611 | ||
612 | Variants are typical constructs in communication protocols with | |
613 | dynamic types. For example, `BSON <http://bsonspec.org/spec.html>`_, | |
614 | the protocol used by `MongoDB <http://www.mongodb.org/>`_, has specific | |
615 | numeric IDs for each element type. | |
616 | ||
617 | This examples shows how to create a CTF variant field. The tag, an | |
618 | enumeration field, must also be created and associated with the | |
619 | variant. In this case, the tag selects between three types: a | |
620 | 32-bit signed integer, a string, or a floating point number. | |
621 | ||
622 | The trace is written in a temporary directory (its path is printed | |
623 | at the beginning of the script). | |
624 | ||
625 | .. code-block:: python | |
626 | ||
627 | import babeltrace.writer as btw | |
628 | import babeltrace.common | |
629 | import tempfile | |
630 | ||
631 | ||
632 | trace_path = tempfile.mkdtemp() | |
633 | ||
634 | print('trace path: {}'.format(trace_path)) | |
635 | ||
636 | ||
637 | writer = btw.Writer(trace_path) | |
638 | ||
639 | clock = btw.Clock('my_clock') | |
640 | clock.description = 'this is my clock' | |
641 | writer.add_clock(clock) | |
642 | ||
643 | stream_class = btw.StreamClass('my_stream') | |
644 | stream_class.clock = clock | |
645 | ||
646 | event_class = btw.EventClass('my_event') | |
647 | ||
648 | # 32-bit signed integer field declaration | |
649 | int32_field_decl = btw.IntegerFieldDeclaration(32) | |
650 | int32_field_decl.signed = True | |
651 | ||
652 | # string field declaration | |
653 | string_field_decl = btw.StringFieldDeclaration() | |
654 | string_field_decl.encoding = babeltrace.common.CTFStringEncoding.UTF8 | |
655 | ||
656 | # IEEE 754 single precision floating point number field declaration | |
657 | float_field_decl = btw.FloatingPointFieldDeclaration() | |
658 | float_field_decl.exponent_digits = btw.FloatingPointFieldDeclaration.FLT_EXP_DIG | |
659 | float_field_decl.mantissa_digits = btw.FloatingPointFieldDeclaration.FLT_MANT_DIG | |
660 | ||
661 | # enumeration field declaration (variant's tag) | |
662 | enum_field_decl = btw.EnumerationFieldDeclaration(int32_field_decl) | |
663 | enum_field_decl.add_mapping('INT', 0, 0) | |
664 | enum_field_decl.add_mapping('STRING', 1, 1) | |
665 | enum_field_decl.add_mapping('FLOAT', 2, 2) | |
666 | ||
667 | # variant field declaration (variant's tag field will be named `vartag`) | |
668 | variant_field_decl = btw.VariantFieldDeclaration(enum_field_decl, 'vartag') | |
669 | ||
670 | # register selectable fields to variant | |
671 | variant_field_decl.add_field(int32_field_decl, 'INT') | |
672 | variant_field_decl.add_field(string_field_decl, 'STRING') | |
673 | variant_field_decl.add_field(float_field_decl, 'FLOAT') | |
674 | ||
675 | event_class.add_field(enum_field_decl, 'vartag') | |
676 | event_class.add_field(variant_field_decl, 'var') | |
677 | ||
678 | stream_class.add_event_class(event_class) | |
679 | ||
680 | stream = writer.create_stream(stream_class) | |
681 | ||
682 | # first event: integer is selected | |
683 | event = btw.Event(event_class) | |
684 | tag_field = event.payload('vartag') | |
685 | tag_field.value = 0 | |
686 | event.payload('var').field(tag_field).value = 23 | |
687 | stream.append_event(event) | |
688 | ||
689 | # second event: string is selected | |
690 | event = btw.Event(event_class) | |
691 | tag_field = event.payload('vartag') | |
692 | tag_field.value = 1 | |
693 | event.payload('var').field(tag_field).value = 'The Battle of Evermore' | |
694 | stream.append_event(event) | |
695 | ||
696 | # third event: floating point number is selected | |
697 | event = btw.Event(event_class) | |
698 | tag_field = event.payload('vartag') | |
699 | tag_field.value = 2 | |
700 | event.payload('var').field(tag_field).value = -15.34 | |
701 | stream.append_event(event) | |
702 | ||
703 | stream.flush() |