2 SPDX-FileCopyrightText: 2020 Philippe Proulx <eeppeliteloop@gmail.com>
3 SPDX-License-Identifier: CC-BY-SA-4.0
5 .. include:: common.rst
11 This section contains a few short and straightforward examples which
12 show how to use the Babeltrace |~| 2 Python bindings.
14 The :mod:`bt2` package provides the Babeltrace |~| 2 Python bindings.
15 Note that the :mod:`babeltrace` package is part of the Babeltrace |~| 1
16 project: it's somewhat out-of-date and not compatible with the
19 Assume that all the examples below are named :file:`example.py`.
25 The most convenient and high-level way to iterate the events of one or
26 more traces is with a :class:`bt2.TraceCollectionMessageIterator`
29 A :class:`bt2.TraceCollectionMessageIterator` object roughly offers the
30 same features as the ``convert`` command of the :command:`babeltrace2`
31 command-line program (see the :bt2man:`babeltrace2-convert(1)` manual
32 page), but in a programmatic, Pythonic way.
34 As of Babeltrace |~| |version|, the trace collection message iterator
35 class is a Python bindings-only feature: the Python code uses
36 libbabeltrace2 internally, but the latter does not offer this utility as
39 The :class:`bt2.TraceCollectionMessageIterator` interface features:
41 * **Automatic source component (trace format) discovery**.
43 ``convert`` command equivalent example:
47 $ babeltrace2 /path/to/my/trace
49 * **Explicit component class instantiation**.
51 ``convert`` command equivalent example:
55 $ babeltrace2 --component=source.my.format
57 * **Passing initialization parameters to both auto-discovered and
58 explicitly created components**.
60 ``convert`` command equivalent example:
64 $ babeltrace2 /path/to/my/trace --params=detailed=no \
65 --component=source.ctf.fs \
66 --params='inputs=["/path/to/my/trace"]'
68 * **Trace event muxing**.
70 The message iterator muxes (combines) the events from multiple
71 compatible streams into a single, time-sorted sequence of events.
75 $ babeltrace2 /path/to/trace1 /path/to/trace2 /path/to/trace3
77 * **Stream intersection mode**.
79 ``convert`` command equivalent example:
83 $ babeltrace2 /path/to/my/trace --stream-intersection
85 * **Stream trimming with beginning and/or end times**.
87 ``convert`` command equivalent example:
91 $ babeltrace2 /path/to/my/trace --begin=22:14:38 --end=22:15:07
93 While the :command:`babeltrace2 convert` command creates a ``sink.text.pretty``
94 component class (by default) to pretty-print events as plain text lines,
95 a :class:`bt2.TraceCollectionMessageIterator` object is a Python
96 iterator which makes its user a message consumer (there's no sink
101 for msg in bt2.TraceCollectionMessageIterator('/path/to/trace'):
102 if type(msg) is bt2._EventMessageConst:
103 print(msg.event.name)
105 .. _examples_tcmi_autodisc:
109 Pass one or more file paths, directory paths, or other strings when you
110 build a :class:`bt2.TraceCollectionMessageIterator` object to let it
111 automatically determine which source components to create for you.
113 If you pass a directory path, the message iterator traverses the
114 directory recursively to find traces, automatically selecting the
115 appropriate source component classes to instantiate.
117 The :class:`bt2.TraceCollectionMessageIterator` object and the
118 :command:`babeltrace2 convert` CLI command share the same automatic
119 component 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>`
121 section of the :bt2man:`babeltrace2-convert(1)` manual page for more
124 The following example shows how to use a
125 :class:`bt2.TraceCollectionMessageIterator` object to automatically
126 discover one or more traces from a single path (file or directory). For
127 each trace event, the example prints its name::
132 # Get the trace path from the first command-line argument.
135 # Create a trace collection message iterator with this path.
136 msg_it = bt2.TraceCollectionMessageIterator(path)
138 # Iterate the trace messages.
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.
145 # Print event's name.
152 $ python3 example.py /path/to/one/or/more/traces
160 kmem_cache_alloc_node
171 The example above is simplistic; it does not catch the exceptions that
172 some statements can raise:
174 * ``bt2.TraceCollectionMessageIterator(path)`` raises an exception if
175 it cannot find any trace.
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.
181 For example, an internal source component message iterator can fail
182 when trying to decode a malformed trace file.
184 .. _examples_tcmi_expl:
186 Create explicit source components
187 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
188 If `automatic source component discovery <#examples-tcmi-autodisc>`_
189 doesn't work for you (for example, because the source component class
190 you actually need to instantiate doesn't offer the
191 ``babeltrace.support-info`` query object), create explicit source
192 components when you build a :class:`bt2.TraceCollectionMessageIterator`
195 The following example builds a trace collection message iterator to
196 explicitly instantiate a ``source.ctf.fs`` component class (found in the
197 ``ctf`` plugin). Again, for each trace event, the example prints its
203 # Find the `ctf` plugin (shipped with Babeltrace 2).
204 ctf_plugin = bt2.find_plugin('ctf')
206 # Get the `source.ctf.fs` component class from the plugin.
207 fs_cc = ctf_plugin.source_component_classes['fs']
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]],
217 # Iterate the trace messages.
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)
228 $ python3 example.py /path/to/ctf/trace
236 kmem_cache_alloc_node
247 The example above looks similar to the previous one using
248 `automatic source component discovery <#examples-tcmi-autodisc>`_,
249 but there are notable differences:
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``).
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.
259 * Unlike the previous example, the example above can only read a single
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``
267 Note that the :class:`bt2.ComponentSpec` class offers the
268 :meth:`from_named_plugin_and_component_class` convenience static method
269 which finds the plugin and component class for you. You could therefore
270 rewrite the trace collection message iterator creation part of the
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]],
283 .. _examples_tcmi_ev_field:
285 Get a specific event field's value
286 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
287 The :ref:`examples_tcmi_autodisc` and :ref:`examples_tcmi_expl` examples
288 show that a :class:`bt2.TraceCollectionMessageIterator` iterates the
289 time-sorted *messages* of one or more traces.
291 One specific type of message is :class:`bt2._EventMessageConst`, which
292 holds a trace event object.
296 Everything you can find in the :mod:`bt2` package is publicly
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
305 .. code-block:: python
307 if type(msg) is bt2._EventMessageConst:
310 .. code-block:: python
312 if isinstance(field, bt2._IntegerFieldConst):
315 Access 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
317 can belong to any part of the event (contexts or payload) and to its
318 packet's context, if any::
323 # Create a trace collection message iterator from the first
324 # command-line argument.
325 msg_it = bt2.TraceCollectionMessageIterator(sys.argv[1])
327 # Iterate the trace messages.
329 # `bt2._EventMessageConst` is the Python type of an event message.
330 # Only keep such messages.
331 if type(msg) is not bt2._EventMessageConst:
334 # An event message holds a trace event.
337 # Only check `sched_switch` events.
338 if event.name != 'sched_switch':
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']
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']
350 # Print line, using field values.
351 msg = 'CPU {}: Switching process `{}` → `{}`'
352 print(msg.format(cpu_id, prev_comm, next_comm))
354 The example above assumes that the traces to open are
355 `LTTng <https://lttng.org/>`_ Linux kernel traces.
361 $ python3 example.py /path/to/one/or/more/lttng/traces
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`
380 If you need to access a specific field, use:
383 :attr:`bt2._EventConst.payload_field` property.
385 Event specific context
386 :attr:`bt2._EventConst.specific_context_field` property.
389 :attr:`bt2._EventConst.common_context_field` property.
392 :attr:`bt2._PacketConst.context_field` property.
394 Use Python's ``in`` operator to verify if:
396 A specific "root" field (in the list above) contains a given field by name
397 .. code-block:: python
399 if 'next_comm' in event.payload_field:
402 Any of the root fields contains a given field by name
403 .. code-block:: python
405 if 'next_comm' in event:
408 The following example iterates the events of a given trace, printing the
409 value of the ``fd`` payload field if it's available::
414 # Create a trace collection message iterator from the first command-line
416 msg_it = bt2.TraceCollectionMessageIterator(sys.argv[1])
418 # Iterate the trace messages.
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'])
444 .. _examples_tcmi_ev_time:
448 The time, or timestamp, of an event object belongs to its message as
449 a *default clock snapshot*.
451 An event's clock snapshot is a *snapshot* (an immutable value) of the
452 value of the event's stream's clock when the event occurred. As of
453 Babeltrace |~| |version|, a stream can only have one clock: its default
456 Use the :attr:`default_clock_snapshot` property of an event message
457 to get its default clock snapshot. A clock snapshot object offers,
458 amongst other things, the following properties:
460 :attr:`value` (:class:`int`)
461 Value of the clock snapshot in clock cycles.
463 A stream clock can have any frequency (Hz).
465 :attr:`ns_from_origin` (:class:`int`)
466 Number of nanoseconds from the stream clock's origin (often the Unix
469 The following example prints, for each event, its name, its date/time,
470 and the difference, in seconds, since the previous event's time (if
477 # Create a trace collection message iterator from the first command-line
479 msg_it = bt2.TraceCollectionMessageIterator(sys.argv[1])
481 # Last event's time (ns from origin).
482 last_event_ns_from_origin = None
484 # Iterate the trace messages.
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
490 ns_from_origin = msg.default_clock_snapshot.ns_from_origin
492 # Compute the time difference since the last event message.
495 if last_event_ns_from_origin is not None:
496 diff_s = (ns_from_origin - last_event_ns_from_origin) / 1e9
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)
504 fmt = '{} (+{:.6f} s): {}'
505 print(fmt.format(dt, diff_s, msg.event.name))
507 # Update last event's time.
508 last_event_ns_from_origin = ns_from_origin
514 $ python3 example.py /path/to/one/or/more/traces
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
530 Bonus: Print top 5 running processes using LTTng
531 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
532 As :ref:`examples_tcmi_ev_field` shows, a
533 :class:`bt2.TraceCollectionMessageIterator` can read
534 `LTTng <https://lttng.org/>`_ traces.
536 The following example is similar to :ref:`examples_tcmi_ev_time`: it
537 reads a whole LTTng Linux kernel trace, but instead of printing the time
538 difference for each event, it accumulates them to print the short names
539 of the top |~| 5 running processes on CPU |~| 0 during the whole trace.
541 .. code-block:: python
547 # Create a trace collection message iterator from the first command-line
549 msg_it = bt2.TraceCollectionMessageIterator(sys.argv[1])
551 # This counter dictionary will hold execution times:
553 # Task command name -> Total execution time (ns)
554 exec_times = collections.Counter()
556 # This holds the last `sched_switch` event time.
557 last_ns_from_origin = None
560 # `bt2._EventMessageConst` is the Python type of an event message.
561 # Only keep such messages.
562 if type(msg) is not bt2._EventMessageConst:
565 # An event message holds a trace event.
568 # Only check `sched_switch` events.
569 if event.name != 'sched_switch':
572 # Keep only events which occurred on CPU 0.
573 if event['cpu_id'] != 0:
576 # Get event message's default clock snapshot's ns from origin value.
577 ns_from_origin = msg.default_clock_snapshot.ns_from_origin
579 if last_ns_from_origin is None:
581 last_ns_from_origin = ns_from_origin
583 # Previous process's short name.
584 prev_comm = str(event['prev_comm'])
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
590 # Compute previous process's execution time.
591 diff_ns = ns_from_origin - last_ns_from_origin
593 # Update execution time of this command.
594 exec_times[prev_comm] += diff_ns
596 # Update last event's time.
597 last_ns_from_origin = ns_from_origin
600 for comm, ns in exec_times.most_common(5):
601 print('{:20}{} s'.format(comm, ns / 1e9))
607 $ python3 example.py /path/to/lttng/trace
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
619 Note that ``swapper/0`` is the "idle" process of CPU |~| 0 on Linux;
620 since we weren't using the CPU that much when tracing, its first
621 position in the list makes sense.
623 Inspect event classes
624 ~~~~~~~~~~~~~~~~~~~~~
625 Each event stream is a *stream class* instance.
627 A stream class contains *event classes*. A stream class's event classes
628 describe all the possible events you can find in its instances. Stream
629 classes and event classes form the *metadata* of streams and events.
631 The following example shows how to list all the event classes of a
632 stream class. For each event class, the example also prints the names of
633 its payload field class's first-level members.
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
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.
645 .. code-block:: python
650 # Create a trace collection message iterator from the first command-line
652 msg_it = bt2.TraceCollectionMessageIterator(sys.argv[1])
654 # Get the message iterator's first stream beginning message.
656 # `bt2._StreamBeginningMessageConst` is the Python type of a stream
658 if type(msg) is bt2._StreamBeginningMessageConst:
661 # A stream beginning message holds a stream.
664 # Get the stream's class.
665 stream_class = stream.cls
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))
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():
679 print(fmt.format(member.name, bt2.__name__,
680 member.field_class.__class__.__name__))
686 $ python3 example.py /path/to/trace
693 comm: `bt2._StringFieldClassConst`
694 tid: `bt2._SignedIntegerFieldClassConst`
695 prio: `bt2._SignedIntegerFieldClassConst`
696 orig_cpu: `bt2._SignedIntegerFieldClassConst`
697 dest_cpu: `bt2._SignedIntegerFieldClassConst`
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`
707 comm: `bt2._StringFieldClassConst`
708 tid: `bt2._SignedIntegerFieldClassConst`
709 prio: `bt2._SignedIntegerFieldClassConst`
710 target_cpu: `bt2._SignedIntegerFieldClassConst`
714 Build and run a trace processing graph
715 --------------------------------------
716 Internally, 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
719 Python iterator interface on top of it.
721 See the :bt2man:`babeltrace2-intro(7)` manual page to learn more about
722 the Babeltrace |~| 2 project and its core concepts.
724 The following examples shows how to manually build and then run a trace
725 processing graph yourself (like the :bt2man:`babeltrace2-run(1)` CLI
726 command does). The general steps to do so are:
728 #. Create an empty graph.
730 #. Add components to the graph.
732 This process is also known as *instantiating a component class*
733 because the graph must first create the component from its class
736 A viable graph contains at least one source component and one sink
739 #. Connect component ports.
741 On initialization, components add input and output ports, depending
744 You can connect component output ports to input ports within a graph.
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.
751 .. code-block:: python
756 # Create an empty graph.
759 # Add a `source.text.dmesg` component.
761 # graph.add_component() returns the created and added component.
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)`.
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')
771 # Add a `sink.text.pretty` component.
773 # Such a component pretty-prints event messages on the standard output
774 # (one message per line). See `babeltrace2-sink.text.pretty(7)`.
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')
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'])
786 # Run the trace processing graph.
793 $ dmesg -t | python3 example.py
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" }
810 Query a component class
811 -----------------------
812 Component classes, provided by plugins, can implement a method to
813 support *query operations*.
815 A query operation is similar to a function call: the caller makes a
816 request (a query) with parameters and the component class's query
817 method returns a result object.
819 The query operation feature exists so that you can benefit from a
820 component class's implementation to get information about a trace, a
821 stream, 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``
824 object to list the available
825 `LTTng live <https://lttng.org/docs/#doc-lttng-live>`_ tracing
826 session names and other properties.
828 The semantics of the query parameters and the returned object are
829 completely defined by the component class implementation: the library
830 and its Python bindings don't enforce or suggest any layout.
831 The best way to know which objects you can query from a component class,
832 what are the expected and optional parameters, and what the returned
833 object contains is to read this component class's documentation.
835 The following example queries the "standard" ``babeltrace.support-info``
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
840 pretty-prints the result. The ``babeltrace.support-info`` query object
841 indicates whether or not a given path locates a
842 :abbr:`CTF (Common Trace Format)` trace directory::
847 # Get the `source.ctf.fs` component class from the `ctf` plugin.
848 comp_cls = bt2.find_plugin('ctf').source_component_classes['fs']
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
855 # See `babeltrace2-query-babeltrace.support-info(7)`.
858 'input': sys.argv[1],
861 # Create a query executor.
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',
869 # Query the component class through the query executor.
871 # This method returns the result.
872 result = query_exec.query()
877 As you can see, no trace processing graph is involved (like in
878 :ref:`examples_tcmi` and :ref:`examples_graph`): a query operation
879 is *not* a sequential trace processing task, but a simple, atomic
886 $ python3 example.py /path/to/ctf/trace
892 {'group': '21c63a42-40bc-4c08-9761-3815ae01f43d', 'weight': 0.75}
894 This 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
896 that this specific CTF trace belongs to the
897 ``21c63a42-40bc-4c08-9761-3815ae01f43d`` group; a single component can
898 handle multiple traces which belong to the same group.
900 Let's try the sample example with a path that doesn't locate a CTF
905 $ python3 example.py /etc
913 As expected, the zero weight indicates that ``/etc`` isn't a CTF trace