doc: bindings: python: lttng version referenced is out of date
[babeltrace.git] / doc / bindings / python / source / examples.rst
CommitLineData
ba64dfcc
SM
1.. include:: common.rst
2
3.. _examples:
4
5Examples
6========
7This section contains a few short and straightforward examples which
8show how to use the Babeltrace |~| 2 Python bindings.
9
10The :mod:`bt2` package provides the Babeltrace |~| 2 Python bindings.
11Note that the :mod:`babeltrace` package is part of the Babeltrace |~| 1
12project: it's somewhat out-of-date and not compatible with the
13:mod:`bt2` package.
14
15Assume that all the examples below are named :file:`example.py`.
16
17.. _examples_tcmi:
18
19Iterate trace events
20--------------------
21The most convenient and high-level way to iterate the events of one or
22more traces is with a :class:`bt2.TraceCollectionMessageIterator`
23object.
24
25A :class:`bt2.TraceCollectionMessageIterator` object roughly offers the
26same features as the ``convert`` command of the :command:`babeltrace2`
27command-line program (see the :bt2man:`babeltrace2-convert(1)` manual
28page), but in a programmatic, Pythonic way.
29
30As of Babeltrace |~| |version|, the trace collection message iterator
31class is a Python bindings-only feature: the Python code uses
32libbabeltrace2 internally, but the latter does not offer this utility as
33such.
34
35The :class:`bt2.TraceCollectionMessageIterator` interface features:
36
37* **Automatic source component (trace format) discovery**.
38
39 ``convert`` command equivalent example:
40
41 .. code-block:: text
42
43 $ babeltrace2 /path/to/my/trace
44
45* **Explicit component class instantiation**.
46
47 ``convert`` command equivalent example:
48
49 .. code-block:: text
50
51 $ babeltrace2 --component=source.my.format
52
53* **Passing initialization parameters to both auto-discovered and
54 explicitly created components**.
55
56 ``convert`` command equivalent example:
57
58 .. code-block:: text
59
60 $ babeltrace2 /path/to/my/trace --params=detailed=no \
61 --component=source.ctf.fs \
62 --params='inputs=["/path/to/my/trace"]'
63
64* **Trace event muxing**.
65
66 The message iterator muxes (combines) the events from multiple
67 compatible streams into a single, time-sorted sequence of events.
68
69 .. code-block:: text
70
71 $ babeltrace2 /path/to/trace1 /path/to/trace2 /path/to/trace3
72
73* **Stream intersection mode**.
74
75 ``convert`` command equivalent example:
76
77 .. code-block:: text
78
79 $ babeltrace2 /path/to/my/trace --stream-intersection
80
81* **Stream trimming with beginning and/or end times**.
82
83 ``convert`` command equivalent example:
84
85 .. code-block:: text
86
87 $ babeltrace2 /path/to/my/trace --begin=22:14:38 --end=22:15:07
88
89While the :command:`babeltrace2 convert` command creates a ``sink.text.pretty``
90component class (by default) to pretty-print events as plain text lines,
91a :class:`bt2.TraceCollectionMessageIterator` object is a Python
92iterator which makes its user a message consumer (there's no sink
93component)::
94
95 import bt2
96
97 for msg in bt2.TraceCollectionMessageIterator('/path/to/trace'):
98 if type(msg) is bt2._EventMessageConst:
99 print(msg.event.name)
100
101.. _examples_tcmi_autodisc:
102
103Discover traces
104~~~~~~~~~~~~~~~
105Pass one or more file paths, directory paths, or other strings when you
106build a :class:`bt2.TraceCollectionMessageIterator` object to let it
107automatically determine which source components to create for you.
108
109If you pass a directory path, the message iterator traverses the
110directory recursively to find traces, automatically selecting the
111appropriate source component classes to instantiate.
112
113The :class:`bt2.TraceCollectionMessageIterator` object and the
114:command:`babeltrace2 convert` CLI command share the same automatic
115component discovery algorithm. See the
116:bt2link:`Create implicit components from non-option arguments <https://babeltrace.org/docs/v@ver@/man1/babeltrace2-convert.1/#doc-comp-create-impl-non-opt>`
117section of the :bt2man:`babeltrace2-convert(1)` manual page for more
118details.
119
120The following example shows how to use a
121:class:`bt2.TraceCollectionMessageIterator` object to automatically
122discover one or more traces from a single path (file or directory). For
123each trace event, the example prints its name::
124
125 import bt2
126 import sys
127
128 # Get the trace path from the first command-line argument.
129 path = sys.argv[1]
130
131 # Create a trace collection message iterator with this path.
132 msg_it = bt2.TraceCollectionMessageIterator(path)
133
134 # Iterate the trace messages.
135 for msg in msg_it:
136 # `bt2._EventMessageConst` is the Python type of an event message.
137 if type(msg) is bt2._EventMessageConst:
138 # An event message holds a trace event.
139 event = msg.event
140
141 # Print event's name.
142 print(event.name)
143
144Run this example:
145
146.. code-block:: text
147
148 $ python3 example.py /path/to/one/or/more/traces
149
150Output example:
151
152.. code-block:: text
153
154 kmem_kmalloc
155 kmem_kfree
156 kmem_cache_alloc_node
157 block_getrq
158 kmem_kmalloc
159 block_plug
160 kmem_kfree
161 block_rq_insert
162 kmem_kmalloc
163 kmem_kfree
164 kmem_kmalloc
165 kmem_kfree
166
167The example above is simplistic; it does not catch the exceptions that
168some statements can raise:
169
170* ``bt2.TraceCollectionMessageIterator(path)`` raises an exception if
171 it cannot find any trace.
172
173* Each iteration of the loop, or, more precisely, the
174 :meth:`bt2.TraceCollectionMessageIterator.__next__` method, raises
175 an exception if there's any error during the iteration process.
176
177 For example, an internal source component message iterator can fail
178 when trying to decode a malformed trace file.
179
180.. _examples_tcmi_expl:
181
182Create explicit source components
183~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
184If `automatic source component discovery <#examples-tcmi-autodisc>`_
185doesn't work for you (for example, because the source component class
186you actually need to instantiate doesn't offer the
187``babeltrace.support-info`` query object), create explicit source
188components when you build a :class:`bt2.TraceCollectionMessageIterator`
189object.
190
191The following example builds a trace collection message iterator to
192explicitly instantiate a ``source.ctf.fs`` component class (found in the
193``ctf`` plugin). Again, for each trace event, the example prints its
194name::
195
196 import bt2
197 import sys
198
199 # Find the `ctf` plugin (shipped with Babeltrace 2).
200 ctf_plugin = bt2.find_plugin('ctf')
201
202 # Get the `source.ctf.fs` component class from the plugin.
203 fs_cc = ctf_plugin.source_component_classes['fs']
204
205 # Create a trace collection message iterator, instantiating a single
206 # `source.ctf.fs` component class with the `inputs` initialization
207 # parameter set to open a single CTF trace.
208 msg_it = bt2.TraceCollectionMessageIterator(bt2.ComponentSpec(fs_cc, {
209 # Get the CTF trace path from the first command-line argument.
210 'inputs': [sys.argv[1]],
211 }))
212
213 # Iterate the trace messages.
214 for msg in msg_it:
215 # `bt2._EventMessageConst` is the Python type of an event message.
216 if type(msg) is bt2._EventMessageConst:
217 # Print event's name.
218 print(msg.event.name)
219
220Run this example:
221
222.. code-block:: text
223
224 $ python3 example.py /path/to/ctf/trace
225
226Output example:
227
228.. code-block:: text
229
230 kmem_kmalloc
231 kmem_kfree
232 kmem_cache_alloc_node
233 block_getrq
234 kmem_kmalloc
235 block_plug
236 kmem_kfree
237 block_rq_insert
238 kmem_kmalloc
239 kmem_kfree
240 kmem_kmalloc
241 kmem_kfree
242
243The example above looks similar to the previous one using
244`automatic source component discovery <#examples-tcmi-autodisc>`_,
245but there are notable differences:
246
247* A ``source.ctf.fs`` component expects to receive the path to a
248 *single* `CTF <https://diamon.org/ctf/>`_ trace (a directory
249 containing a file named ``metadata``).
250
251 Unlike the previous example, you must pass the exact
252 :abbr:`CTF (Common Trace Format)` trace directory path, *not* a
253 parent directory path.
254
255* Unlike the previous example, the example above can only read a single
256 trace.
257
258 If you want to read multiple :abbr:`CTF (Common Trace Format)` traces
259 using explicit component class instantiation with a single trace
260 collection message iterator, you must create one ``source.ctf.fs``
261 component per trace.
262
263Note that the :class:`bt2.ComponentSpec` class offers the
264:meth:`from_named_plugin_and_component_class` convenience static method
265which finds the plugin and component class for you. You could therefore
266rewrite the trace collection message iterator creation part of the
267example above as::
268
269 # Create a trace collection message iterator, instantiating a single
270 # `source.ctf.fs` component class with the `inputs` initialization
271 # parameter set to open a single CTF trace.
272 msg_it = bt2.TraceCollectionMessageIterator(
273 bt2.ComponentSpec.from_named_plugin_and_component_class('ctf', 'fs', {
274 # Get the CTF trace path from the first command-line argument.
275 'inputs': [sys.argv[1]],
276 })
277 )
278
279.. _examples_tcmi_ev_field:
280
281Get a specific event field's value
282~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
283The :ref:`examples_tcmi_autodisc` and :ref:`examples_tcmi_expl` examples
284show that a :class:`bt2.TraceCollectionMessageIterator` iterates the
285time-sorted *messages* of one or more traces.
286
287One specific type of message is :class:`bt2._EventMessageConst`, which
288holds a trace event object.
289
290.. note::
291
292 Everything you can find in the :mod:`bt2` package is publicly
293 accessible.
294
295 Names which start with ``_`` (underscore), like
296 :class:`bt2._EventMessageConst`, indicate that you can't
297 *instantiate* such a class (you cannot call the class). However, the
298 type itself remains public so that you can use its name to check an
299 object's type:
300
301 .. code-block:: python
302
303 if type(msg) is bt2._EventMessageConst:
304 # ...
305
306 .. code-block:: python
307
308 if isinstance(field, bt2._IntegerFieldConst):
309 # ...
310
311Access an event object's field by using the event as a simple mapping
312(like a read-only :class:`dict`), where keys are field names. The field
313can belong to any part of the event (contexts or payload) and to its
314packet's context, if any::
315
316 import bt2
317 import sys
318
319 # Create a trace collection message iterator from the first
320 # command-line argument.
321 msg_it = bt2.TraceCollectionMessageIterator(sys.argv[1])
322
323 # Iterate the trace messages.
324 for msg in msg_it:
325 # `bt2._EventMessageConst` is the Python type of an event message.
326 # Only keep such messages.
327 if type(msg) is not bt2._EventMessageConst:
328 continue
329
330 # An event message holds a trace event.
331 event = msg.event
332
333 # Only check `sched_switch` events.
334 if event.name != 'sched_switch':
335 continue
336
337 # In an LTTng trace, the `cpu_id` field is a packet context field.
338 # The mapping interface of `event` can still find it.
339 cpu_id = event['cpu_id']
340
341 # Previous and next process short names are found in the event's
342 # `prev_comm` and `next_comm` fields.
343 prev_comm = event['prev_comm']
344 next_comm = event['next_comm']
345
346 # Print line, using field values.
347 msg = 'CPU {}: Switching process `{}` → `{}`'
348 print(msg.format(cpu_id, prev_comm, next_comm))
349
350The example above assumes that the traces to open are
351`LTTng <https://lttng.org/>`_ Linux kernel traces.
352
353Run this example:
354
355.. code-block:: text
356
357 $ python3 example.py /path/to/one/or/more/lttng/traces
358
359Output example:
360
361.. code-block:: text
362
363 CPU 2: Switching process `Timer` → `swapper/2`
364 CPU 0: Switching process `swapper/0` → `firefox`
365 CPU 0: Switching process `firefox` → `swapper/0`
366 CPU 0: Switching process `swapper/0` → `rcu_preempt`
367 CPU 0: Switching process `rcu_preempt` → `swapper/0`
368 CPU 3: Switching process `swapper/3` → `alsa-sink-ALC26`
369 CPU 2: Switching process `swapper/2` → `Timer`
370 CPU 2: Switching process `Timer` → `swapper/2`
371 CPU 2: Switching process `swapper/2` → `pulseaudio`
372 CPU 0: Switching process `swapper/0` → `firefox`
373 CPU 1: Switching process `swapper/1` → `threaded-ml`
374 CPU 2: Switching process `pulseaudio` → `Timer`
375
376If you need to access a specific field, use:
377
378Event payload
379 :attr:`bt2._EventConst.payload_field` property.
380
381Event specific context
382 :attr:`bt2._EventConst.specific_context_field` property.
383
384Event common context
385 :attr:`bt2._EventConst.common_context_field` property.
386
387Packet context
388 :attr:`bt2._PacketConst.context_field` property.
389
390Use Python's ``in`` operator to verify if:
391
392A specific "root" field (in the list above) contains a given field by name
393 .. code-block:: python
394
395 if 'next_comm' in event.payload_field:
396 # ...
397
398Any of the root fields contains a given field by name
399 .. code-block:: python
400
401 if 'next_comm' in event:
402 # ...
403
404The following example iterates the events of a given trace, printing the
405value of the ``fd`` payload field if it's available::
406
407 import bt2
408 import sys
409
410 # Create a trace collection message iterator from the first command-line
411 # argument.
412 msg_it = bt2.TraceCollectionMessageIterator(sys.argv[1])
413
414 # Iterate the trace messages.
415 for msg in msg_it:
416 # `bt2._EventMessageConst` is the Python type of an event message.
417 if type(msg) is bt2._EventMessageConst:
418 # Check if the `fd` event payload field exists.
419 if 'fd' in msg.event.payload_field:
420 # Print the `fd` event payload field's value.
421 print(msg.event.payload_field['fd'])
422
423Output example:
424
425.. code-block:: text
426
427 14
428 15
429 16
430 19
431 30
432 31
433 33
434 42
435 0
436 1
437 2
438 3
439
440.. _examples_tcmi_ev_time:
441
442Get an event's time
443~~~~~~~~~~~~~~~~~~~
444The time, or timestamp, of an event object belongs to its message as
445a *default clock snapshot*.
446
447An event's clock snapshot is a *snapshot* (an immutable value) of the
448value of the event's stream's clock when the event occurred. As of
449Babeltrace |~| |version|, a stream can only have one clock: its default
450clock.
451
452Use the :attr:`default_clock_snapshot` property of an event message
453to get its default clock snapshot. A clock snapshot object offers,
454amongst other things, the following properties:
455
456:attr:`value` (:class:`int`)
457 Value of the clock snapshot in clock cycles.
458
459 A stream clock can have any frequency (Hz).
460
461:attr:`ns_from_origin` (:class:`int`)
462 Number of nanoseconds from the stream clock's origin (often the Unix
463 epoch).
464
465The following example prints, for each event, its name, its date/time,
466and the difference, in seconds, since the previous event's time (if
467any)::
468
469 import bt2
470 import sys
471 import datetime
472
473 # Create a trace collection message iterator from the first command-line
474 # argument.
475 msg_it = bt2.TraceCollectionMessageIterator(sys.argv[1])
476
477 # Last event's time (ns from origin).
478 last_event_ns_from_origin = None
479
480 # Iterate the trace messages.
481 for msg in msg_it:
482 # `bt2._EventMessageConst` is the Python type of an event message.
483 if type(msg) is bt2._EventMessageConst:
484 # Get event message's default clock snapshot's ns from origin
485 # value.
486 ns_from_origin = msg.default_clock_snapshot.ns_from_origin
487
488 # Compute the time difference since the last event message.
489 diff_s = 0
490
491 if last_event_ns_from_origin is not None:
492 diff_s = (ns_from_origin - last_event_ns_from_origin) / 1e9
493
494 # Create a `datetime.datetime` object from `ns_from_origin` for
495 # presentation. Note that such an object is less accurate than
496 # `ns_from_origin` as it holds microseconds, not nanoseconds.
497 dt = datetime.datetime.fromtimestamp(ns_from_origin / 1e9)
498
499 # Print line.
500 fmt = '{} (+{:.6f} s): {}'
501 print(fmt.format(dt, diff_s, msg.event.name))
502
503 # Update last event's time.
504 last_event_ns_from_origin = ns_from_origin
505
506Run this example:
507
508.. code-block:: text
509
510 $ python3 example.py /path/to/one/or/more/traces
511
512Output example:
513
514.. code-block:: text
515
516 2015-09-09 22:40:41.551451 (+0.000004 s): lttng_ust_statedump:end
517 2015-09-09 22:40:43.003397 (+1.451946 s): lttng_ust_dl:dlopen
518 2015-09-09 22:40:43.003412 (+0.000015 s): lttng_ust_dl:build_id
519 2015-09-09 22:40:43.003861 (+0.000449 s): lttng_ust_dl:dlopen
520 2015-09-09 22:40:43.003865 (+0.000004 s): lttng_ust_dl:build_id
521 2015-09-09 22:40:43.003879 (+0.000014 s): my_provider:my_first_tracepoint
522 2015-09-09 22:40:43.003895 (+0.000016 s): my_provider:my_first_tracepoint
523 2015-09-09 22:40:43.003898 (+0.000003 s): my_provider:my_other_tracepoint
524 2015-09-09 22:40:43.003922 (+0.000023 s): lttng_ust_dl:dlclose
525
526Bonus: Print top 5 running processes using LTTng
527~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
528As :ref:`examples_tcmi_ev_field` shows, a
529:class:`bt2.TraceCollectionMessageIterator` can read
530`LTTng <https://lttng.org/>`_ traces.
531
532The following example is similar to :ref:`examples_tcmi_ev_time`: it
533reads a whole LTTng Linux kernel trace, but instead of printing the time
534difference for each event, it accumulates them to print the short names
535of the top |~| 5 running processes on CPU |~| 0 during the whole trace.
536
537.. code-block:: python
538
539 import bt2
540 import sys
541 import collections
542
543 # Create a trace collection message iterator from the first command-line
544 # argument.
545 msg_it = bt2.TraceCollectionMessageIterator(sys.argv[1])
546
547 # This counter dictionary will hold execution times:
548 #
549 # Task command name -> Total execution time (ns)
550 exec_times = collections.Counter()
551
552 # This holds the last `sched_switch` event time.
553 last_ns_from_origin = None
554
555 for msg in msg_it:
556 # `bt2._EventMessageConst` is the Python type of an event message.
557 # Only keep such messages.
558 if type(msg) is not bt2._EventMessageConst:
559 continue
560
561 # An event message holds a trace event.
562 event = msg.event
563
564 # Only check `sched_switch` events.
565 if event.name != 'sched_switch':
566 continue
567
568 # Keep only events which occurred on CPU 0.
569 if event['cpu_id'] != 0:
570 continue
571
572 # Get event message's default clock snapshot's ns from origin value.
573 ns_from_origin = msg.default_clock_snapshot.ns_from_origin
574
575 if last_ns_from_origin is None:
576 # We start here.
577 last_ns_from_origin = ns_from_origin
578
579 # Previous process's short name.
580 prev_comm = str(event['prev_comm'])
581
582 # Initialize an entry in our dictionary if not done yet.
583 if prev_comm not in exec_times:
584 exec_times[prev_comm] = 0
585
586 # Compute previous process's execution time.
587 diff_ns = ns_from_origin - last_ns_from_origin
588
589 # Update execution time of this command.
590 exec_times[prev_comm] += diff_ns
591
592 # Update last event's time.
593 last_ns_from_origin = ns_from_origin
594
595 # Print top 5.
596 for comm, ns in exec_times.most_common(5):
597 print('{:20}{} s'.format(comm, ns / 1e9))
598
599Run this example:
600
601.. code-block:: text
602
603 $ python3 example.py /path/to/lttng/trace
604
605Output example:
606
607.. code-block:: text
608
609 swapper/0 326.294314471 s
610 chromium 2.500456202 s
611 Xorg.bin 0.546656895 s
612 threaded-ml 0.545098185 s
613 pulseaudio 0.53677713 s
614
615Note that ``swapper/0`` is the "idle" process of CPU |~| 0 on Linux;
616since we weren't using the CPU that much when tracing, its first
617position in the list makes sense.
618
619Inspect event classes
620~~~~~~~~~~~~~~~~~~~~~
621Each event stream is a *stream class* instance.
622
623A stream class contains *event classes*. A stream class's event classes
624describe all the possible events you can find in its instances. Stream
625classes and event classes form the *metadata* of streams and events.
626
627The following example shows how to list all the event classes of a
628stream class. For each event class, the example also prints the names of
629its payload field class's first-level members.
630
631.. note::
632
633 As of Babeltrace |~| |version|, there's no way to access a stream class
634 without consuming at least one message for one of its instances
635 (streams).
636
637 A source component can add new event classes to existing stream
638 classes during the trace processing task. Therefore, this example
639 only lists the initial stream class's event classes.
640
641.. code-block:: python
642
643 import bt2
644 import sys
645
646 # Create a trace collection message iterator from the first command-line
647 # argument.
648 msg_it = bt2.TraceCollectionMessageIterator(sys.argv[1])
649
650 # Get the message iterator's first stream beginning message.
651 for msg in msg_it:
652 # `bt2._StreamBeginningMessageConst` is the Python type of a stream
653 # beginning message.
654 if type(msg) is bt2._StreamBeginningMessageConst:
655 break
656
657 # A stream beginning message holds a stream.
658 stream = msg.stream
659
660 # Get the stream's class.
661 stream_class = stream.cls
662
663 # The stream class object offers a mapping interface (like a read-only
664 # `dict`), where keys are event class IDs and values are
665 # `bt2._EventClassConst` objects.
666 for event_class in stream_class.values():
667 print('{}:'.format(event_class.name))
668
669 # The `payload_field_class` property of an event class returns a
670 # `bt2._StructureFieldClassConst` object. This object offers a
671 # mapping interface, where keys are member names and values are
672 # `bt2._StructureFieldClassMemberConst` objects.
673 for member in event_class.payload_field_class.values():
674 fmt = ' {}: `{}.{}`'
675 print(fmt.format(member.name, bt2.__name__,
676 member.field_class.__class__.__name__))
677
678Run this example:
679
680.. code-block:: text
681
682 $ python3 example.py /path/to/trace
683
684Output example:
685
686.. code-block:: text
687
688 sched_migrate_task:
689 comm: `bt2._StringFieldClassConst`
690 tid: `bt2._SignedIntegerFieldClassConst`
691 prio: `bt2._SignedIntegerFieldClassConst`
692 orig_cpu: `bt2._SignedIntegerFieldClassConst`
693 dest_cpu: `bt2._SignedIntegerFieldClassConst`
694 sched_switch:
695 prev_comm: `bt2._StringFieldClassConst`
696 prev_tid: `bt2._SignedIntegerFieldClassConst`
697 prev_prio: `bt2._SignedIntegerFieldClassConst`
698 prev_state: `bt2._SignedIntegerFieldClassConst`
699 next_comm: `bt2._StringFieldClassConst`
700 next_tid: `bt2._SignedIntegerFieldClassConst`
701 next_prio: `bt2._SignedIntegerFieldClassConst`
702 sched_wakeup_new:
703 comm: `bt2._StringFieldClassConst`
704 tid: `bt2._SignedIntegerFieldClassConst`
705 prio: `bt2._SignedIntegerFieldClassConst`
706 target_cpu: `bt2._SignedIntegerFieldClassConst`
707
708.. _examples_graph:
709
710Build and run a trace processing graph
711--------------------------------------
712Internally, a :class:`bt2.TraceCollectionMessageIterator` object (see
713:ref:`examples_tcmi`) builds a *trace processing graph*, just like the
714:bt2man:`babeltrace2-convert(1)` CLI command, and then offers a
715Python iterator interface on top of it.
716
717See the :bt2man:`babeltrace2-intro(7)` manual page to learn more about
718the Babeltrace |~| 2 project and its core concepts.
719
720The following examples shows how to manually build and then run a trace
721processing graph yourself (like the :bt2man:`babeltrace2-run(1)` CLI
722command does). The general steps to do so are:
723
724#. Create an empty graph.
725
726#. Add components to the graph.
727
728 This process is also known as *instantiating a component class*
729 because the graph must first create the component from its class
730 before adding it.
731
732 A viable graph contains at least one source component and one sink
733 component.
734
735#. Connect component ports.
736
737 On initialization, components add input and output ports, depending
738 on their type.
739
740 You can connect component output ports to input ports within a graph.
741
742#. Run the graph.
743
744 This is a blocking operation which makes each sink component consume
745 some messages in a round robin fashion until there are no more.
746
747.. code-block:: python
748
749 import bt2
750 import sys
751
752 # Create an empty graph.
753 graph = bt2.Graph()
754
755 # Add a `source.text.dmesg` component.
756 #
757 # graph.add_component() returns the created and added component.
758 #
759 # Such a component reads Linux kernel ring buffer messages (see
760 # `dmesg(1)`) from the standard input and creates corresponding event
761 # messages. See `babeltrace2-source.text.dmesg(7)`.
762 #
763 # `my source` is the unique name of this component within `graph`.
764 comp_cls = bt2.find_plugin('text').source_component_classes['dmesg']
765 src_comp = graph.add_component(comp_cls, 'my source')
766
767 # Add a `sink.text.pretty` component.
768 #
769 # Such a component pretty-prints event messages on the standard output
770 # (one message per line). See `babeltrace2-sink.text.pretty(7)`.
771 #
772 # The `babeltrace2 convert` CLI command uses a `sink.text.pretty`
773 # sink component by default.
774 comp_cls = bt2.find_plugin('text').sink_component_classes['pretty']
775 sink_comp = graph.add_component(comp_cls, 'my sink')
776
777 # Connect the `out` output port of the `source.text.dmesg` component
778 # to the `in` input port of the `sink.text.pretty` component.
779 graph.connect_ports(src_comp.output_ports['out'],
780 sink_comp.input_ports['in'])
781
782 # Run the trace processing graph.
783 graph.run()
784
785Run this example:
786
787.. code-block:: text
788
789 $ dmesg -t | python3 example.py
790
791Output example:
792
793.. code-block:: text
794
795 string: { str = "ata1.00: NCQ Send/Recv Log not supported" }
796 string: { str = "ata1.00: ACPI cmd ef/02:00:00:00:00:a0 (SET FEATURES) succeeded" }
797 string: { str = "ata1.00: ACPI cmd f5/00:00:00:00:00:a0 (SECURITY FREEZE LOCK) filtered out" }
798 string: { str = "ata1.00: ACPI cmd ef/10:03:00:00:00:a0 (SET FEATURES) filtered out" }
799 string: { str = "ata1.00: NCQ Send/Recv Log not supported" }
800 string: { str = "ata1.00: configured for UDMA/133" }
801 string: { str = "ata1.00: Enabling discard_zeroes_data" }
802 string: { str = "OOM killer enabled." }
803 string: { str = "Restarting tasks ... done." }
804 string: { str = "PM: suspend exit" }
805
806Query a component class
807-----------------------
808Component classes, provided by plugins, can implement a method to
809support *query operations*.
810
811A query operation is similar to a function call: the caller makes a
812request (a query) with parameters and the component class's query
813method returns a result object.
814
815The query operation feature exists so that you can benefit from a
816component class's implementation to get information about a trace, a
817stream, a distant server, and so on. For example, the
818``source.ctf.lttng-live`` component class (see
819:bt2man:`babeltrace2-source.ctf.lttng-live(7)`) offers the ``sessions``
820object to list the available
ec3bf3f1 821`LTTng live <https://lttng.org/docs/#doc-lttng-live>`_ tracing
ba64dfcc
SM
822session names and other properties.
823
824The semantics of the query parameters and the returned object are
825completely defined by the component class implementation: the library
826and its Python bindings don't enforce or suggest any layout.
827The best way to know which objects you can query from a component class,
828what are the expected and optional parameters, and what the returned
829object contains is to read this component class's documentation.
830
831The following example queries the "standard" ``babeltrace.support-info``
832query object (see
833:bt2man:`babeltrace2-query-babeltrace.support-info(7)`) from the
834``source.ctf.fs`` component class
835(see :bt2man:`babeltrace2-source.ctf.fs(7)`) and
836pretty-prints the result. The ``babeltrace.support-info`` query object
837indicates whether or not a given path locates a
838:abbr:`CTF (Common Trace Format)` trace directory::
839
840 import bt2
841 import sys
842
843 # Get the `source.ctf.fs` component class from the `ctf` plugin.
844 comp_cls = bt2.find_plugin('ctf').source_component_classes['fs']
845
846 # The `babeltrace.support-info` query operation expects a `type`
847 # parameter (set to `directory` here) and an `input` parameter (the
848 # actual path or string to check, in this case the first command-line
849 # argument).
850 #
851 # See `babeltrace2-query-babeltrace.support-info(7)`.
852 params = {
853 'type': 'directory',
854 'input': sys.argv[1],
855 }
856
857 # Create a query executor.
858 #
859 # This is the environment in which query operations happens. The
860 # queried component class has access to this executor, for example to
861 # retrieve the query operation's logging level.
862 query_exec = bt2.QueryExecutor(comp_cls, 'babeltrace.support-info',
863 params)
864
865 # Query the component class through the query executor.
866 #
867 # This method returns the result.
868 result = query_exec.query()
869
870 # Print the result.
871 print(result)
872
873As you can see, no trace processing graph is involved (like in
874:ref:`examples_tcmi` and :ref:`examples_graph`): a query operation
875is *not* a sequential trace processing task, but a simple, atomic
876procedure call.
877
878Run this example:
879
880.. code-block:: text
881
882 $ python3 example.py /path/to/ctf/trace
883
884Output example:
885
886.. code-block:: text
887
888 {'group': '21c63a42-40bc-4c08-9761-3815ae01f43d', 'weight': 0.75}
889
890This result indicates that the component class is 75 |~| % confident that
891:file:`/path/to/ctf/trace` is a CTF trace directory path. It also shows
892that this specific CTF trace belongs to the
893``21c63a42-40bc-4c08-9761-3815ae01f43d`` group; a single component can
894handle multiple traces which belong to the same group.
895
896Let's try the sample example with a path that doesn't locate a CTF
897trace:
898
899.. code-block:: text
900
901 $ python3 example.py /etc
902
903Output:
904
905.. code-block:: text
906
907 {'weight': 0.0}
908
909As expected, the zero weight indicates that ``/etc`` isn't a CTF trace
910directory path.
This page took 0.05349 seconds and 4 git commands to generate.