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