1 .. include:: common.rst
7 This section contains a few short and straightforward examples which
8 show how to use the Babeltrace |~| 2 Python bindings.
10 The :mod:`bt2` package provides the Babeltrace |~| 2 Python bindings.
11 Note that the :mod:`babeltrace` package is part of the Babeltrace |~| 1
12 project: it's somewhat out-of-date and not compatible with the
15 Assume that all the examples below are named :file:`example.py`.
21 The most convenient and high-level way to iterate the events of one or
22 more traces is with a :class:`bt2.TraceCollectionMessageIterator`
25 A :class:`bt2.TraceCollectionMessageIterator` object roughly offers the
26 same features as the ``convert`` command of the :command:`babeltrace2`
27 command-line program (see the :bt2man:`babeltrace2-convert(1)` manual
28 page), but in a programmatic, Pythonic way.
30 As of Babeltrace |~| |version|, the trace collection message iterator
31 class is a Python bindings-only feature: the Python code uses
32 libbabeltrace2 internally, but the latter does not offer this utility as
35 The :class:`bt2.TraceCollectionMessageIterator` interface features:
37 * **Automatic source component (trace format) discovery**.
39 ``convert`` command equivalent example:
43 $ babeltrace2 /path/to/my/trace
45 * **Explicit component class instantiation**.
47 ``convert`` command equivalent example:
51 $ babeltrace2 --component=source.my.format
53 * **Passing initialization parameters to both auto-discovered and
54 explicitly created components**.
56 ``convert`` command equivalent example:
60 $ babeltrace2 /path/to/my/trace --params=detailed=no \
61 --component=source.ctf.fs \
62 --params='inputs=["/path/to/my/trace"]'
64 * **Trace event muxing**.
66 The message iterator muxes (combines) the events from multiple
67 compatible streams into a single, time-sorted sequence of events.
71 $ babeltrace2 /path/to/trace1 /path/to/trace2 /path/to/trace3
73 * **Stream intersection mode**.
75 ``convert`` command equivalent example:
79 $ babeltrace2 /path/to/my/trace --stream-intersection
81 * **Stream trimming with beginning and/or end times**.
83 ``convert`` command equivalent example:
87 $ babeltrace2 /path/to/my/trace --begin=22:14:38 --end=22:15:07
89 While the :command:`babeltrace2 convert` command creates a ``sink.text.pretty``
90 component class (by default) to pretty-print events as plain text lines,
91 a :class:`bt2.TraceCollectionMessageIterator` object is a Python
92 iterator which makes its user a message consumer (there's no sink
97 for msg in bt2.TraceCollectionMessageIterator('/path/to/trace'):
98 if type(msg) is bt2._EventMessageConst:
101 .. _examples_tcmi_autodisc:
105 Pass one or more file paths, directory paths, or other strings when you
106 build a :class:`bt2.TraceCollectionMessageIterator` object to let it
107 automatically determine which source components to create for you.
109 If you pass a directory path, the message iterator traverses the
110 directory recursively to find traces, automatically selecting the
111 appropriate source component classes to instantiate.
113 The :class:`bt2.TraceCollectionMessageIterator` object and the
114 :command:`babeltrace2 convert` CLI command share the same automatic
115 component 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>`
117 section of the :bt2man:`babeltrace2-convert(1)` manual page for more
120 The following example shows how to use a
121 :class:`bt2.TraceCollectionMessageIterator` object to automatically
122 discover one or more traces from a single path (file or directory). For
123 each trace event, the example prints its name::
128 # Get the trace path from the first command-line argument.
131 # Create a trace collection message iterator with this path.
132 msg_it = bt2.TraceCollectionMessageIterator(path)
134 # Iterate the trace messages.
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.
141 # Print event's name.
148 $ python3 example.py /path/to/one/or/more/traces
156 kmem_cache_alloc_node
167 The example above is simplistic; it does not catch the exceptions that
168 some statements can raise:
170 * ``bt2.TraceCollectionMessageIterator(path)`` raises an exception if
171 it cannot find any trace.
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.
177 For example, an internal source component message iterator can fail
178 when trying to decode a malformed trace file.
180 .. _examples_tcmi_expl:
182 Create explicit source components
183 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
184 If `automatic source component discovery <#examples-tcmi-autodisc>`_
185 doesn't work for you (for example, because the source component class
186 you actually need to instantiate doesn't offer the
187 ``babeltrace.support-info`` query object), create explicit source
188 components when you build a :class:`bt2.TraceCollectionMessageIterator`
191 The following example builds a trace collection message iterator to
192 explicitly instantiate a ``source.ctf.fs`` component class (found in the
193 ``ctf`` plugin). Again, for each trace event, the example prints its
199 # Find the `ctf` plugin (shipped with Babeltrace 2).
200 ctf_plugin = bt2.find_plugin('ctf')
202 # Get the `source.ctf.fs` component class from the plugin.
203 fs_cc = ctf_plugin.source_component_classes['fs']
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]],
213 # Iterate the trace messages.
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)
224 $ python3 example.py /path/to/ctf/trace
232 kmem_cache_alloc_node
243 The example above looks similar to the previous one using
244 `automatic source component discovery <#examples-tcmi-autodisc>`_,
245 but there are notable differences:
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``).
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.
255 * Unlike the previous example, the example above can only read a single
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``
263 Note that the :class:`bt2.ComponentSpec` class offers the
264 :meth:`from_named_plugin_and_component_class` convenience static method
265 which finds the plugin and component class for you. You could therefore
266 rewrite the trace collection message iterator creation part of the
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]],
279 .. _examples_tcmi_ev_field:
281 Get a specific event field's value
282 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
283 The :ref:`examples_tcmi_autodisc` and :ref:`examples_tcmi_expl` examples
284 show that a :class:`bt2.TraceCollectionMessageIterator` iterates the
285 time-sorted *messages* of one or more traces.
287 One specific type of message is :class:`bt2._EventMessageConst`, which
288 holds a trace event object.
292 Everything you can find in the :mod:`bt2` package is publicly
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
301 .. code-block:: python
303 if type(msg) is bt2._EventMessageConst:
306 .. code-block:: python
308 if isinstance(field, bt2._IntegerFieldConst):
311 Access 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
313 can belong to any part of the event (contexts or payload) and to its
314 packet's context, if any::
319 # Create a trace collection message iterator from the first
320 # command-line argument.
321 msg_it = bt2.TraceCollectionMessageIterator(sys.argv[1])
323 # Iterate the trace messages.
325 # `bt2._EventMessageConst` is the Python type of an event message.
326 # Only keep such messages.
327 if type(msg) is not bt2._EventMessageConst:
330 # An event message holds a trace event.
333 # Only check `sched_switch` events.
334 if event.name != 'sched_switch':
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']
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']
346 # Print line, using field values.
347 msg = 'CPU {}: Switching process `{}` → `{}`'
348 print(msg.format(cpu_id, prev_comm, next_comm))
350 The example above assumes that the traces to open are
351 `LTTng <https://lttng.org/>`_ Linux kernel traces.
357 $ python3 example.py /path/to/one/or/more/lttng/traces
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`
376 If you need to access a specific field, use:
379 :attr:`bt2._EventConst.payload_field` property.
381 Event specific context
382 :attr:`bt2._EventConst.specific_context_field` property.
385 :attr:`bt2._EventConst.common_context_field` property.
388 :attr:`bt2._PacketConst.context_field` property.
390 Use Python's ``in`` operator to verify if a specific "root" field (in the list
391 above) contains a given field by name::
393 if 'next_comm' in event.payload_field:
396 The following example iterates the events of a given trace, printing the
397 value of the ``fd`` payload field if it's available::
402 # Create a trace collection message iterator from the first command-line
404 msg_it = bt2.TraceCollectionMessageIterator(sys.argv[1])
406 # Iterate the trace messages.
408 # `bt2._EventMessageConst` is the Python type of an event message.
409 if type(msg) is bt2._EventMessageConst:
410 # Check if the `fd` event payload field exists.
411 if 'fd' in msg.event.payload_field:
412 # Print the `fd` event payload field's value.
413 print(msg.event.payload_field['fd'])
432 .. _examples_tcmi_ev_time:
436 The time, or timestamp, of an event object belongs to its message as
437 a *default clock snapshot*.
439 An event's clock snapshot is a *snapshot* (an immutable value) of the
440 value of the event's stream's clock when the event occurred. As of
441 Babeltrace |~| |version|, a stream can only have one clock: its default
444 Use the :attr:`default_clock_snapshot` property of an event message
445 to get its default clock snapshot. A clock snapshot object offers,
446 amongst other things, the following properties:
448 :attr:`value` (:class:`int`)
449 Value of the clock snapshot in clock cycles.
451 A stream clock can have any frequency (Hz).
453 :attr:`ns_from_origin` (:class:`int`)
454 Number of nanoseconds from the stream clock's origin (often the Unix
457 The following example prints, for each event, its name, its date/time,
458 and the difference, in seconds, since the previous event's time (if
465 # Create a trace collection message iterator from the first command-line
467 msg_it = bt2.TraceCollectionMessageIterator(sys.argv[1])
469 # Last event's time (ns from origin).
470 last_event_ns_from_origin = None
472 # Iterate the trace messages.
474 # `bt2._EventMessageConst` is the Python type of an event message.
475 if type(msg) is bt2._EventMessageConst:
476 # Get event message's default clock snapshot's ns from origin
478 ns_from_origin = msg.default_clock_snapshot.ns_from_origin
480 # Compute the time difference since the last event message.
483 if last_event_ns_from_origin is not None:
484 diff_s = (ns_from_origin - last_event_ns_from_origin) / 1e9
486 # Create a `datetime.datetime` object from `ns_from_origin` for
487 # presentation. Note that such an object is less accurate than
488 # `ns_from_origin` as it holds microseconds, not nanoseconds.
489 dt = datetime.datetime.fromtimestamp(ns_from_origin / 1e9)
492 fmt = '{} (+{:.6f} s): {}'
493 print(fmt.format(dt, diff_s, msg.event.name))
495 # Update last event's time.
496 last_event_ns_from_origin = ns_from_origin
502 $ python3 example.py /path/to/one/or/more/traces
508 2015-09-09 22:40:41.551451 (+0.000004 s): lttng_ust_statedump:end
509 2015-09-09 22:40:43.003397 (+1.451946 s): lttng_ust_dl:dlopen
510 2015-09-09 22:40:43.003412 (+0.000015 s): lttng_ust_dl:build_id
511 2015-09-09 22:40:43.003861 (+0.000449 s): lttng_ust_dl:dlopen
512 2015-09-09 22:40:43.003865 (+0.000004 s): lttng_ust_dl:build_id
513 2015-09-09 22:40:43.003879 (+0.000014 s): my_provider:my_first_tracepoint
514 2015-09-09 22:40:43.003895 (+0.000016 s): my_provider:my_first_tracepoint
515 2015-09-09 22:40:43.003898 (+0.000003 s): my_provider:my_other_tracepoint
516 2015-09-09 22:40:43.003922 (+0.000023 s): lttng_ust_dl:dlclose
518 Bonus: Print top 5 running processes using LTTng
519 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
520 As :ref:`examples_tcmi_ev_field` shows, a
521 :class:`bt2.TraceCollectionMessageIterator` can read
522 `LTTng <https://lttng.org/>`_ traces.
524 The following example is similar to :ref:`examples_tcmi_ev_time`: it
525 reads a whole LTTng Linux kernel trace, but instead of printing the time
526 difference for each event, it accumulates them to print the short names
527 of the top |~| 5 running processes on CPU |~| 0 during the whole trace.
529 .. code-block:: python
535 # Create a trace collection message iterator from the first command-line
537 msg_it = bt2.TraceCollectionMessageIterator(sys.argv[1])
539 # This counter dictionary will hold execution times:
541 # Task command name -> Total execution time (ns)
542 exec_times = collections.Counter()
544 # This holds the last `sched_switch` event time.
545 last_ns_from_origin = None
548 # `bt2._EventMessageConst` is the Python type of an event message.
549 # Only keep such messages.
550 if type(msg) is not bt2._EventMessageConst:
553 # An event message holds a trace event.
556 # Only check `sched_switch` events.
557 if event.name != 'sched_switch':
560 # Keep only events which occurred on CPU 0.
561 if event['cpu_id'] != 0:
564 # Get event message's default clock snapshot's ns from origin value.
565 ns_from_origin = msg.default_clock_snapshot.ns_from_origin
567 if last_ns_from_origin is None:
569 last_ns_from_origin = ns_from_origin
571 # Previous process's short name.
572 prev_comm = str(event['prev_comm'])
574 # Initialize an entry in our dictionary if not done yet.
575 if prev_comm not in exec_times:
576 exec_times[prev_comm] = 0
578 # Compute previous process's execution time.
579 diff_ns = ns_from_origin - last_ns_from_origin
581 # Update execution time of this command.
582 exec_times[prev_comm] += diff_ns
584 # Update last event's time.
585 last_ns_from_origin = ns_from_origin
588 for comm, ns in exec_times.most_common(5):
589 print('{:20}{} s'.format(comm, ns / 1e9))
595 $ python3 example.py /path/to/lttng/trace
601 swapper/0 326.294314471 s
602 chromium 2.500456202 s
603 Xorg.bin 0.546656895 s
604 threaded-ml 0.545098185 s
605 pulseaudio 0.53677713 s
607 Note that ``swapper/0`` is the "idle" process of CPU |~| 0 on Linux;
608 since we weren't using the CPU that much when tracing, its first
609 position in the list makes sense.
611 Inspect event classes
612 ~~~~~~~~~~~~~~~~~~~~~
613 Each event stream is a *stream class* instance.
615 A stream class contains *event classes*. A stream class's event classes
616 describe all the possible events you can find in its instances. Stream
617 classes and event classes form the *metadata* of streams and events.
619 The following example shows how to list all the event classes of a
620 stream class. For each event class, the example also prints the names of
621 its payload field class's first-level members.
625 As of Babeltrace |~| |version|, there's no way to access a stream class
626 without consuming at least one message for one of its instances
629 A source component can add new event classes to existing stream
630 classes during the trace processing task. Therefore, this example
631 only lists the initial stream class's event classes.
633 .. code-block:: python
638 # Create a trace collection message iterator from the first command-line
640 msg_it = bt2.TraceCollectionMessageIterator(sys.argv[1])
642 # Get the message iterator's first stream beginning message.
644 # `bt2._StreamBeginningMessageConst` is the Python type of a stream
646 if type(msg) is bt2._StreamBeginningMessageConst:
649 # A stream beginning message holds a stream.
652 # Get the stream's class.
653 stream_class = stream.cls
655 # The stream class object offers a mapping interface (like a read-only
656 # `dict`), where keys are event class IDs and values are
657 # `bt2._EventClassConst` objects.
658 for event_class in stream_class.values():
659 print('{}:'.format(event_class.name))
661 # The `payload_field_class` property of an event class returns a
662 # `bt2._StructureFieldClassConst` object. This object offers a
663 # mapping interface, where keys are member names and values are
664 # `bt2._StructureFieldClassMemberConst` objects.
665 for member in event_class.payload_field_class.values():
667 print(fmt.format(member.name, bt2.__name__,
668 member.field_class.__class__.__name__))
674 $ python3 example.py /path/to/trace
681 comm: `bt2._StringFieldClassConst`
682 tid: `bt2._SignedIntegerFieldClassConst`
683 prio: `bt2._SignedIntegerFieldClassConst`
684 orig_cpu: `bt2._SignedIntegerFieldClassConst`
685 dest_cpu: `bt2._SignedIntegerFieldClassConst`
687 prev_comm: `bt2._StringFieldClassConst`
688 prev_tid: `bt2._SignedIntegerFieldClassConst`
689 prev_prio: `bt2._SignedIntegerFieldClassConst`
690 prev_state: `bt2._SignedIntegerFieldClassConst`
691 next_comm: `bt2._StringFieldClassConst`
692 next_tid: `bt2._SignedIntegerFieldClassConst`
693 next_prio: `bt2._SignedIntegerFieldClassConst`
695 comm: `bt2._StringFieldClassConst`
696 tid: `bt2._SignedIntegerFieldClassConst`
697 prio: `bt2._SignedIntegerFieldClassConst`
698 target_cpu: `bt2._SignedIntegerFieldClassConst`
702 Build and run a trace processing graph
703 --------------------------------------
704 Internally, a :class:`bt2.TraceCollectionMessageIterator` object (see
705 :ref:`examples_tcmi`) builds a *trace processing graph*, just like the
706 :bt2man:`babeltrace2-convert(1)` CLI command, and then offers a
707 Python iterator interface on top of it.
709 See the :bt2man:`babeltrace2-intro(7)` manual page to learn more about
710 the Babeltrace |~| 2 project and its core concepts.
712 The following examples shows how to manually build and then run a trace
713 processing graph yourself (like the :bt2man:`babeltrace2-run(1)` CLI
714 command does). The general steps to do so are:
716 #. Create an empty graph.
718 #. Add components to the graph.
720 This process is also known as *instantiating a component class*
721 because the graph must first create the component from its class
724 A viable graph contains at least one source component and one sink
727 #. Connect component ports.
729 On initialization, components add input and output ports, depending
732 You can connect component output ports to input ports within a graph.
736 This is a blocking operation which makes each sink component consume
737 some messages in a round robin fashion until there are no more.
739 .. code-block:: python
744 # Create an empty graph.
747 # Add a `source.text.dmesg` component.
749 # graph.add_component() returns the created and added component.
751 # Such a component reads Linux kernel ring buffer messages (see
752 # `dmesg(1)`) from the standard input and creates corresponding event
753 # messages. See `babeltrace2-source.text.dmesg(7)`.
755 # `my source` is the unique name of this component within `graph`.
756 comp_cls = bt2.find_plugin('text').source_component_classes['dmesg']
757 src_comp = graph.add_component(comp_cls, 'my source')
759 # Add a `sink.text.pretty` component.
761 # Such a component pretty-prints event messages on the standard output
762 # (one message per line). See `babeltrace2-sink.text.pretty(7)`.
764 # The `babeltrace2 convert` CLI command uses a `sink.text.pretty`
765 # sink component by default.
766 comp_cls = bt2.find_plugin('text').sink_component_classes['pretty']
767 sink_comp = graph.add_component(comp_cls, 'my sink')
769 # Connect the `out` output port of the `source.text.dmesg` component
770 # to the `in` input port of the `sink.text.pretty` component.
771 graph.connect_ports(src_comp.output_ports['out'],
772 sink_comp.input_ports['in'])
774 # Run the trace processing graph.
781 $ dmesg -t | python3 example.py
787 string: { str = "ata1.00: NCQ Send/Recv Log not supported" }
788 string: { str = "ata1.00: ACPI cmd ef/02:00:00:00:00:a0 (SET FEATURES) succeeded" }
789 string: { str = "ata1.00: ACPI cmd f5/00:00:00:00:00:a0 (SECURITY FREEZE LOCK) filtered out" }
790 string: { str = "ata1.00: ACPI cmd ef/10:03:00:00:00:a0 (SET FEATURES) filtered out" }
791 string: { str = "ata1.00: NCQ Send/Recv Log not supported" }
792 string: { str = "ata1.00: configured for UDMA/133" }
793 string: { str = "ata1.00: Enabling discard_zeroes_data" }
794 string: { str = "OOM killer enabled." }
795 string: { str = "Restarting tasks ... done." }
796 string: { str = "PM: suspend exit" }
798 Query a component class
799 -----------------------
800 Component classes, provided by plugins, can implement a method to
801 support *query operations*.
803 A query operation is similar to a function call: the caller makes a
804 request (a query) with parameters and the component class's query
805 method returns a result object.
807 The query operation feature exists so that you can benefit from a
808 component class's implementation to get information about a trace, a
809 stream, a distant server, and so on. For example, the
810 ``source.ctf.lttng-live`` component class (see
811 :bt2man:`babeltrace2-source.ctf.lttng-live(7)`) offers the ``sessions``
812 object to list the available
813 `LTTng live <https://lttng.org/docs/#doc-lttng-live>`_ tracing
814 session names and other properties.
816 The semantics of the query parameters and the returned object are
817 completely defined by the component class implementation: the library
818 and its Python bindings don't enforce or suggest any layout.
819 The best way to know which objects you can query from a component class,
820 what are the expected and optional parameters, and what the returned
821 object contains is to read this component class's documentation.
823 The following example queries the "standard" ``babeltrace.support-info``
825 :bt2man:`babeltrace2-query-babeltrace.support-info(7)`) from the
826 ``source.ctf.fs`` component class
827 (see :bt2man:`babeltrace2-source.ctf.fs(7)`) and
828 pretty-prints the result. The ``babeltrace.support-info`` query object
829 indicates whether or not a given path locates a
830 :abbr:`CTF (Common Trace Format)` trace directory::
835 # Get the `source.ctf.fs` component class from the `ctf` plugin.
836 comp_cls = bt2.find_plugin('ctf').source_component_classes['fs']
838 # The `babeltrace.support-info` query operation expects a `type`
839 # parameter (set to `directory` here) and an `input` parameter (the
840 # actual path or string to check, in this case the first command-line
843 # See `babeltrace2-query-babeltrace.support-info(7)`.
846 'input': sys.argv[1],
849 # Create a query executor.
851 # This is the environment in which query operations happens. The
852 # queried component class has access to this executor, for example to
853 # retrieve the query operation's logging level.
854 query_exec = bt2.QueryExecutor(comp_cls, 'babeltrace.support-info',
857 # Query the component class through the query executor.
859 # This method returns the result.
860 result = query_exec.query()
865 As you can see, no trace processing graph is involved (like in
866 :ref:`examples_tcmi` and :ref:`examples_graph`): a query operation
867 is *not* a sequential trace processing task, but a simple, atomic
874 $ python3 example.py /path/to/ctf/trace
880 {'group': '21c63a42-40bc-4c08-9761-3815ae01f43d', 'weight': 0.75}
882 This result indicates that the component class is 75 |~| % confident that
883 :file:`/path/to/ctf/trace` is a CTF trace directory path. It also shows
884 that this specific CTF trace belongs to the
885 ``21c63a42-40bc-4c08-9761-3815ae01f43d`` group; a single component can
886 handle multiple traces which belong to the same group.
888 Let's try the sample example with a path that doesn't locate a CTF
893 $ python3 example.py /etc
901 As expected, the zero weight indicates that ``/etc`` isn't a CTF trace