python: make all _get_ref/_put_ref proper static methods
[babeltrace.git] / CONTRIBUTING.adoc
... / ...
CommitLineData
1// Render with Asciidoctor
2
3= Babeltrace{nbsp}2 contributor's guide
4Jérémie Galarneau, Philippe Proulx
51 December 2020
6:toc: left
7:toclevels: 3
8:icons: font
9:nofooter:
10:bt2: Babeltrace{nbsp}2
11:c-cpp: C/{cpp}
12:cpp11: {cpp}11
13
14This is a partial contributor's guide for the
15https://babeltrace.org[{bt2}] project. If you have any
16questions that are not answered by this guide, please post them on
17https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev[Babeltrace's
18mailing list].
19
20== {bt2} library
21
22=== Object reference counting and lifetime
23
24This section covers the rationale behind the design of {bt2}'s
25object lifetime management. This applies to the {bt2} library, as
26well as to the CTF writer library (although the public reference
27counting functions are not named the same way).
28
29Starting from Babeltrace{nbsp}2.0, all publicly exposed objects inherit
30a common base: `bt_object`. This base provides a number of facilities to
31all objects, chief amongst which are lifetime management functions.
32
33The lifetime of some public objects is managed by reference counting. In
34this case, the API offers the `+bt_*_get_ref()+` and `+bt_*_put_ref()+`
35functions which respectively increment and decrement an object's
36reference count.
37
38As far as lifetime management in concerned, {bt2} makes a clear
39distinction between regular objects, which have a single parent, and
40root objects, which don't.
41
42==== The problem
43
44Let us consider a problematic case to illustrate the need for this
45distinction.
46
47A user of the {bt2} library creates a trace class, which _has_ a
48stream class (the class of a stream) and that stream class, in turn,
49_has_ an event class (the class of an event).
50
51Nothing prevents this user from releasing his reference on any one of
52these objects in any order. However, all objects in the
53__trace--stream class--event class__ hierarchy can be retrieved
54from any other.
55
56For instance, the user could discard his reference on both the event
57class and the stream class, only keeping a reference on the trace class.
58From this trace class reference, stream classes can be enumerated,
59providing the user with a new reference to the stream class he discarded
60earlier. Event classes can also be enumerated from stream classes,
61providing the user with references to the individual event classes.
62
63Conversely, the user could also hold a reference to an event class and
64retrieve its parent stream class. The trace class, in turn, can then be
65retrieved from the stream class.
66
67This example illustrates what could be interpreted as a circular
68reference dependency existing between these objects. Of course, if the
69objects in such a scenario were to hold references to each other (in
70both directions), we would be in presence of a circular ownership
71resulting in a leak of both objects as their reference counts would
72never reach zero.
73
74Nonetheless, the API must offer the guarantee that holding a node to any
75node of the graph keeps all other reachable nodes alive.
76
77==== The solution
78
79The scheme employed in {bt2} to break this cycle consists in the
80"children" holding _reverse component references_ to their parents. That
81is, in the context of the trace IR, that event classes hold a reference
82to their parent stream class and stream classes hold a reference to
83their parent trace class.
84
85On the other hand, parents hold _claiming aggregation references_ to
86their children. A claiming aggregation reference means that the object
87being referenced should not be deleted as long as the reference still
88exists. In this respect, it can be said that parents truly hold the
89ownership of their children, since they control their lifetime.
90Conversely, the reference counting mechanism is leveraged by children to
91notify parents that no other child indirectly exposes the parent.
92
93When a parented object's reference count reaches zero, it invokes
94`+bt_*_put_ref()+` on its parent and does _not_ free itself. However,
95from that point, the object depends on its parent to signal the moment
96when it can be safely reclaimed.
97
98The invocation of `+bt_*_put_ref()+` by the last children holding a
99reference to its parent might trigger a cascade of `+bt_*_put_ref()+`
100from child to parent. Eventually, a **root** object is reached. At that
101point, if this orphaned object's reference count reaches zero, the
102object invokes the destructor method defined by everyone of its children
103as part of their base `struct bt_object`. The key point here is that the
104cascade of destructor will necessarily originate from the root and
105propagate in preorder to the children. These children will propagate the
106destruction to their own children before reclaiming their own memory.
107This ensures that a node's pointer to its parent is _always_ valid since
108the parent has the responsibility of tearing-down their children before
109cleaning themselves up.
110
111Assuming a reference to an object is _acquired_ by calling
112`+bt_*_get_ref()+` while its reference count is zero, the object
113acquires, in turn, a reference on its parent using `+bt_*_get_ref()+`.
114At that point, the child can be thought of as having converted its weak
115reference to its parent into a regular reference. That is why this
116reference is referred to as a _claiming_ aggregation reference.
117
118==== Caveats
119
120This scheme imposes a number of strict rules defining the relation
121between objects:
122
123* Objects may only have one parent.
124* Objects, beside the root, are only retrievable from their direct
125 parent or children.
126
127==== Example
128
129The initial situation is rather simple: **User{nbsp}A** is holding a
130reference to a trace class, **TC1**. As per the rules previously
131enounced, stream classes **SC1** and **SC2** don't hold a reference to
132**TC1** since their own reference counts are zero. The same holds true
133for **EC1**, **EC2** and **EC3** with respect to **SC1** and **SC2**.
134
135image::doc/contributing-images/bt-ref01.png[]
136
137In this second step, we can see that **User{nbsp}A** has acquired a
138reference on **SC2** through the trace class, **TC1**.
139
140The stream class's reference count transitions from zero to one,
141triggering the acquisition of a strong reference on **TC1** from
142**SC2**.
143
144Hence, at this point, the trace class's ownership is shared by
145**User{nbsp}A** and **SC2**.
146
147image::doc/contributing-images/bt-ref02.png[]
148
149Next, **User{nbsp}A** acquires a reference on the **EC3** event class
150through its parent stream class, **SC2**. Again, the transition of an
151object's reference count from 0 to 1 triggers the acquisition of a
152reference on its parent.
153
154Note that SC2's reference count was incremented to 2. The trace class's
155reference count remains unchanged.
156
157image::doc/contributing-images/bt-ref03.png[]
158
159**User{nbsp}A** decides to drop its reference on **SC2**. **SC2**'s
160reference count returns back to 1, everything else remaining unchanged.
161
162image::doc/contributing-images/bt-ref04.png[]
163
164**User{nbsp}A** can then decide to drop its reference on the trace
165class. This results in a reversal of the initial situation:
166**User{nbsp}A** now owns an event, **EC3**, which is keeping everything
167else alive and reachable.
168
169image::doc/contributing-images/bt-ref05.png[]
170
171If another object, **User{nbsp}B**, enters the picture and acquires a
172reference on the **SC1** stream class, we see that **SC1**'s reference
173count transitioned from 0 to 1, triggering the acquisition of a
174reference on **TC1**.
175
176image::doc/contributing-images/bt-ref06.png[]
177
178**User{nbsp}B** hands off a reference to **EC1**, acquired through
179**SC1**, to another object, **User{nbsp}C**. The acquisition of a
180reference on **EC1**, which transitions from 0 to 1, triggers the
181acquisition of a reference on its parent, **SC1**.
182
183image::doc/contributing-images/bt-ref07.png[]
184
185At some point, **User{nbsp}A** releases its reference on **EC3**. Since
186**EC3**'s reference count transitions to zero, it releases its reference
187on **SC2**. **SC2**'s reference count, in turn, reaches zero and it
188releases its reference to **TC1**.
189
190**TC1**'s reference count is now 1 and no further action is taken.
191
192image::doc/contributing-images/bt-ref08.png[]
193
194**User{nbsp}B** releases its reference on **SC1**. **User{nbsp}C**
195becomes the sole owner of the whole hierarchy through his ownership of
196**EC1**.
197
198image::doc/contributing-images/bt-ref09.png[]
199
200Finally, **User{nbsp}C** releases his ownership of **EC1**, triggering
201the release of the whole hierarchy. Let's walk through the reclamation
202of the whole graph.
203
204Mirroring what happened when **User{nbsp}A** released its last reference
205on **EC3**, the release of **EC1** by **User{nbsp}C** causes its
206reference count to fall to zero.
207
208This transition to zero causes **EC1** to release its reference on
209**SC1**. **SC1**'s reference count reaching zero causes it to release
210its reference on **TC1**.
211
212image::doc/contributing-images/bt-ref10.png[]
213
214Since the reference count of **TC1**, a root object, has reached zero,
215it invokes the destructor method on its children. This method is
216recursive and causes the stream classes to call the destructor method on
217their event classes.
218
219The event classes are reached and, having no children of their own, are
220reclaimed.
221
222image::doc/contributing-images/bt-ref11.png[]
223
224The stream classes having destroyed their children, are then reclaimed
225by the trace class.
226
227image::doc/contributing-images/bt-ref12.png[]
228
229Finally, the stream classes having been reclaimed, **TC1** is reclaimed.
230
231image::doc/contributing-images/bt-ref13.png[]
232
233
234== Logging
235
236Logging is a great instrument for a developer to be able to collect
237information about a running software.
238
239{bt2} is a complex software with many layers. When a {bt2}
240graph fails to run, what caused the failure? It could be caused by any
241component, any message iterator, and any deeply nested validation of a
242CTF IR object (within the `ctf` plugin), for example. With the
243appropriate logging statements manually placed in the source code, we
244can find the cause of a bug faster.
245
246While <<choose-a-log-level,care must be taken>> when placing _DEBUG_ to
247_FATAL_ logging statements, you should liberally instrument your
248{bt2} module with _TRACE_ logging statements to help future you
249and other developers understand what's happening at run time.
250
251=== Logging API
252
253The {bt2} logging API is internal: it is not exposed to the users
254of the library; only to their developers. The only thing that a library
255user can control is the current log level of the library itself with
256`bt_logging_set_global_level()` and the initial library's log level with
257the `LIBBABELTRACE2_INIT_LOG_LEVEL` environment variable.
258
259This API is based on https://github.com/wonder-mice/zf_log[zf_log], a
260lightweight, yet featureful, MIT-licensed core logging library for C and
261{cpp}. The zf_log source files were modified to have the `BT_` and
262`bt_` prefixes, and other small changes, like color support and using
263the project's `BT_DEBUG_MODE` definition instead of the standard
264`NDEBUG`.
265
266The logging functions are implemented in the logging convenience
267library (`src/logging` directory).
268
269[[logging-headers]]
270==== Headers
271
272The logging API headers are:
273
274`<babeltrace2/logging.h>`::
275 Public header which a library user can use to set and get
276 libbabeltrace2's current log level.
277
278`"logging/log.h"`::
279 Internal, generic logging API which you can use in any {bt2}
280 module. This is the translation of `zf_log.h`.
281+
282This header offers the <<gen-logging-statements,generic logging
283statement macros>>.
284
285`"lib/logging.h"`::
286 Specific internal header to use within the library.
287+
288This header defines `BT_LOG_OUTPUT_LEVEL` to a custom, library-wide
289hidden symbol which is the library's current log level before including
290`"logging/log.h"`.
291+
292This header offers the <<lib-logging-statements,library-specific logging
293statement macros>>.
294
295`"logging/comp-logging.h"`::
296 Specific internal header to use within a component class.
297+
298This header offers the <<comp-logging-statements,component-specific
299logging statement macros>>.
300
301[[log-levels]]
302==== Log levels
303
304The internal logging API offers the following log levels, in ascending
305order of severity:
306
307[options="header,autowidth",cols="4"]
308|===
309|Log level name
310|Log level short name
311|Internal API enumerator
312|Public API enumerator
313
314|_TRACE_
315|`T`
316|`BT_LOG_TRACE`
317|`BT_LOGGING_LEVEL_TRACE`
318
319|_DEBUG_
320|`D`
321|`BT_LOG_DEBUG`
322|`BT_LOGGING_LEVEL_DEBUG`
323
324|_INFO_
325|`I`
326|`BT_LOG_INFO`
327|`BT_LOGGING_LEVEL_INFO`
328
329|_WARNING_
330|`W`
331|`BT_LOG_WARNING`
332|`BT_LOGGING_LEVEL_WARNING`
333
334|_ERROR_
335|`E`
336|`BT_LOG_ERROR`
337|`BT_LOGGING_LEVEL_ERROR`
338
339|_FATAL_
340|`F`
341|`BT_LOG_FATAL`
342|`BT_LOGGING_LEVEL_FATAL`
343
344|_NONE_
345|`N`
346|`BT_LOG_NONE`
347|`BT_LOGGING_LEVEL_NONE`
348|===
349
350The short name is accepted by the log level environment variables and by
351the CLI's `--log-level` options.
352
353See <<choose-a-log-level,how to decide which one to use>> below.
354
355There are two important log level expressions:
356
357[[build-time-log-level]]Build-time, minimal log level::
358 The minimal log level, or build-time log level, is set at build time
359 and determines the minimal log level of the logging statements which
360 can be executed. This applies to all the modules (CLI, library,
361 plugins, bindings, etc.).
362+
363All the logging statements with a level below this level are **not built
364at all**. All the logging statements with a level equal to or greater
365than this level _can_ be executed, depending on the
366<<run-time-log-level,run-time log level>>.
367+
368You can set this level at configuration time with the
369`BABELTRACE_MINIMAL_LOG_LEVEL` environment variable, for example:
370+
371--
372----
373$ BABELTRACE_MINIMAL_LOG_LEVEL=INFO ./configure
374----
375--
376+
377The default build-time log level is `DEBUG`. For optimal performance,
378set it to `INFO`, which effectively disables all fast path logging in
379all the {bt2} modules. You can't set it to `WARNING`, `ERROR`,
380`FATAL`, or `NONE` because the impact on performance is minuscule
381starting from the _INFO_ log level anyway and we want any {bt2}
382build to always be able to print _INFO_-level logs.
383+
384The library's public API provides `bt_logging_get_minimal_level()` to
385get the configured minimal log level.
386
387[[run-time-log-level]]Run-time, dynamic log level::
388 The dynamic log level is set at run time and determines the current,
389 _active_ log level. All the logging statements with a level below
390 this level are not executed, **but they still evaluate the
391 condition**. All the logging statements with a level equal to or
392 greater than this level are executed, provided that their level is
393 also <<build-time-log-level,enabled at build time>>.
394+
395`zf_log` has a concept of a global run-time log level which uses the
396`_bt_log_global_output_lvl` symbol. In practice, we never use this
397symbol, and always make sure that `BT_LOG_OUTPUT_LEVEL` is defined to a
398module-wise expression before including `"logging/log.h"`.
399+
400In the library, `"lib/logging.h"` defines its own
401`BT_LOG_OUTPUT_LEVEL` to the library's log level symbol before it
402includes `"logging/log.h"` itself.
403+
404In libbabeltrace2, the user can set the current run-time log level with
405the `bt_logging_set_global_level()` function, for example:
406+
407--
408[source,c]
409----
410bt_logging_set_global_level(BT_LOGGING_LEVEL_INFO);
411----
412--
413+
414The library's initial run-time log level is defined by the
415`LIBBABELTRACE2_INIT_LOG_LEVEL` environment variable, or set to _NONE_
416if this environment variable is undefined.
417+
418Other modules have their own way of setting their run-time log level.
419+
420For example, the CLI uses the `BABELTRACE_CLI_LOG_LEVEL` environment
421variable, as well as its global `--log-level` option:
422+
423----
424$ babeltrace2 --log-level=I ...
425----
426+
427The components use their own log level (as returned by
428`bt_component_get_logging_level()`). With the CLI, you can set a
429specific component's log level with its own, position-dependent
430`--log-level` option:
431+
432----
433$ babeltrace2 /path/to/trace -c sink.ctf.fs --log-level=D
434----
435+
436Code which is common to the whole project, for example `src/common`
437and `src/compat`, use function parameters to get its run-time log
438level, for example:
439+
440[source,c]
441----
442char *bt_common_get_home_plugin_path(int log_level);
443----
444+
445Typically, when a logging-enabled module calls such a function, it
446passes its own log level expression directly (`BT_LOG_OUTPUT_LEVEL`):
447+
448[source,c]
449----
450path = bt_common_get_home_plugin_path(BT_LOG_OUTPUT_LEVEL);
451----
452+
453Otherwise, just pass `BT_LOG_NONE`:
454+
455----
456path = bt_common_get_home_plugin_path(BT_LOG_NONE);
457----
458
459[[gen-logging-statements]]
460==== Generic logging statement macros
461
462The {bt2} logging statement macros work just like `printf()`
463(except the `+BT_LOG*_STR()+` ones) and contain their <<log-levels,log
464level>> (short name) in their name.
465
466Each of the following macros evaluate the
467<<build-time-log-level,build-time log level>> definition and
468<<run-time-log-level,run-time log level>> expression (as defined by
469`BT_LOG_OUTPUT_LEVEL`) to log conditionally.
470
471See <<logging-instrument-c-file-gen>> and
472<<logging-instrument-h-file-gen>> to learn how to be able to use the
473following macros.
474
475`+BT_LOGT("format string", ...)+`::
476 Generic trace logging statement.
477
478`+BT_LOGD("format string", ...)+`::
479 Generic debug logging statement.
480
481`+BT_LOGI("format string", ...)+`::
482 Generic info logging statement.
483
484`+BT_LOGW("format string", ...)+`::
485 Generic warning logging statement.
486
487`+BT_LOGE("format string", ...)+`::
488 Generic error logging statement.
489
490`+BT_LOGF("format string", ...)+`::
491 Generic fatal logging statement.
492
493`+BT_LOGT_STR("preformatted string")+`::
494 Generic preformatted string trace logging statement.
495
496`+BT_LOGD_STR("preformatted string")+`::
497 Generic preformatted string debug logging statement.
498
499`+BT_LOGI_STR("preformatted string")+`::
500 Generic preformatted string info logging statement.
501
502`+BT_LOGW_STR("preformatted string")+`::
503 Generic preformatted string warning logging statement.
504
505`+BT_LOGE_STR("preformatted string")+`::
506 Generic preformatted string error logging statement.
507
508`+BT_LOGF_STR("preformatted string")+`::
509 Generic preformatted string fatal logging statement.
510
511`+BT_LOGT_MEM(data_ptr, data_size, "format string", ...)+`::
512 Generic memory trace logging statement.
513
514`+BT_LOGD_MEM(data_ptr, data_size, "format string", ...)+`::
515 Generic memory debug logging statement.
516
517`+BT_LOGI_MEM(data_ptr, data_size, "format string", ...)+`::
518 Generic memory info logging statement.
519
520`+BT_LOGW_MEM(data_ptr, data_size, "format string", ...)+`::
521 Generic memory warning logging statement.
522
523`+BT_LOGE_MEM(data_ptr, data_size, "format string", ...)+`::
524 Generic memory error logging statement.
525
526`+BT_LOGF_MEM(data_ptr, data_size, "format string", ...)+`::
527 Generic memory fatal logging statement.
528
529`+BT_LOGT_ERRNO("initial message", "format string", ...)+`::
530 Generic `errno` string trace logging statement.
531
532`+BT_LOGD_ERRNO("initial message", "format string", ...)+`::
533 Generic `errno` string debug logging statement.
534
535`+BT_LOGI_ERRNO("initial message", "format string", ...)+`::
536 Generic `errno` string info logging statement.
537
538`+BT_LOGW_ERRNO("initial message", "format string", ...)+`::
539 Generic `errno` string warning logging statement.
540
541`+BT_LOGE_ERRNO("initial message", "format string", ...)+`::
542 Generic `errno` string error logging statement.
543
544`+BT_LOGF_ERRNO("initial message", "format string", ...)+`::
545 Generic `errno` string fatal logging statement.
546
547[[lib-logging-statements]]
548==== Library-specific logging statement macros
549
550The {bt2} library contains an internal logging API based on the
551generic logging framework. You can use it to log known {bt2}
552objects without having to manually log each member.
553
554See <<logging-instrument-c-file-lib>>
555and <<logging-instrument-h-file-lib>> to
556learn how to be able to use the following macros.
557
558The library logging statement macros are named `+BT_LIB_LOG*()+` instead
559of `+BT_LOG*()+`:
560
561`+BT_LIB_LOGT("format string", ...)+`::
562 Library trace logging statement.
563
564`+BT_LIB_LOGD("format string", ...)+`::
565 Library debug logging statement.
566
567`+BT_LIB_LOGI("format string", ...)+`::
568 Library info logging statement.
569
570`+BT_LIB_LOGW("format string", ...)+`::
571 Library warning logging statement.
572
573`+BT_LIB_LOGE("format string", ...)+`::
574 Library error logging statement.
575
576`+BT_LIB_LOGF("format string", ...)+`::
577 Library fatal logging statement.
578
579`+BT_LIB_LOGW_APPEND_CAUSE("format string", ...)+`::
580 Library warning logging statement, and unconditional error cause
581 appending.
582
583`+BT_LIB_LOGE_APPEND_CAUSE("format string", ...)+`::
584 Library error logging statement, and unconditional error cause
585 appending.
586
587The macros above accept the typical `printf()` conversion specifiers
588with the following limitations:
589
590* The `+*+` width specifier is not accepted.
591* The `+*+` precision specifier is not accepted.
592* The `j` and `t` length modifiers are not accepted.
593* The `n` format specifier is not accepted.
594* The format specifiers defined in `<inttypes.h>` are not accepted,
595 except for `PRId64`, `PRIu64`, `PRIx64`, `PRIX64`, `PRIo64`, and
596 `PRIi64`.
597
598The {bt2} library custom conversion specifier is accepted. Its
599syntax is either `%!u` to format a UUID (`bt_uuid` type), or:
600
601. Introductory `%!` sequence.
602
603. **Optional**: `[` followed by a custom prefix for the printed fields
604 of this specifier, followed by `]`. The standard form is to end this
605 prefix with `-` so that, for example, with the prefix `tc-`, the
606 complete field name becomes `tc-addr`.
607
608. **Optional**: `pass:[+]` to print extended object members. This
609 depends on the provided format specifier.
610
611. Format specifier (see below).
612
613The available format specifiers are:
614
615[options="header,autowidth",cols="3"]
616|===
617|Specifier
618|Object
619|Expected C type
620
621|`F`
622|Trace IR field class
623|`+const struct bt_field_class *+`
624
625|`f`
626|Trace IR field
627|`+const struct bt_field *+`
628
629|`P`
630|Trace IR field path
631|`+const struct bt_field_path *+`
632
633|`E`
634|Trace IR event class
635|`+const struct bt_event_class *+`
636
637|`e`
638|Trace IR event
639|`+const struct bt_event *+`
640
641|`S`
642|Trace IR stream class.
643|`+const struct bt_stream_class *+`
644
645|`s`
646|Trace IR stream
647|`+const struct bt_stream *+`
648
649|`a`
650|Trace IR packet
651|`+const struct bt_packet *+`
652
653|`T`
654|Trace IR trace class
655|`+const struct bt_trace_class *+`
656
657|`t`
658|Trace IR trace
659|`+const struct bt_trace *+`
660
661|`K`
662|Trace IR clock class
663|`+const struct bt_clock_class *+`
664
665|`k`
666|Trace IR clock snapshot
667|`+const struct bt_clock_snapshot *+`
668
669|`v`
670|Value object
671|`+const struct bt_value *+`
672
673|`R`
674|Integer range set
675|`const struct bt_integer_range_set *`
676
677|`n`
678|Message
679|`+const struct bt_message *+`
680
681|`I`
682|Message iterator class
683|`struct bt_message_iterator_class *`
684
685|`i`
686|Message iterator
687|`struct bt_message_iterator *`
688
689|`C`
690|Component class
691|`struct bt_component_class *`
692
693|`c`
694|Component
695|`+const struct bt_component *+`
696
697|`p`
698|Port
699|`+const struct bt_port *+`
700
701|`x`
702|Connection
703|`+const struct bt_connection *+`
704
705|`g`
706|Graph
707|`+const struct bt_graph *+`
708
709|`z`
710|Interrupter
711|`+struct bt_interrupter *+`
712
713|`l`
714|Plugin
715|`+const struct bt_plugin *+`
716
717|`r`
718|Error cause
719|`+const struct bt_error_cause *+`
720
721|`o`
722|Object pool
723|`+const struct bt_object_pool *+`
724
725|`O`
726|Object
727|`+const struct bt_object *+`
728|===
729
730Conversion specifier examples:
731
732* `%!f`
733* `%![my-event-]+e`
734* `%!t`
735* `%!+F`
736
737The ``, `` string (comma and space) is printed between individual
738fields, but **not after the last one**. Therefore, you must put this
739separator in the format string between two conversion specifiers, for
740example:
741
742[source,c]
743----
744BT_LIB_LOGW("Message: count=%u, %!E, %!+K", count, event_class, clock_class);
745----
746
747Example with a custom prefix:
748
749[source,c]
750----
751BT_LIB_LOGI("Some message: %![ec-a-]e, %![ec-b-]+e", ec_a, ec_b);
752----
753
754It is safe to pass `NULL` as any {bt2} object parameter: the macros
755only print its null address.
756
757WARNING: Build-time `printf()` format checks are disabled for the
758`+BT_LIB_LOG*()+` macros because there are custom conversion specifiers,
759so make sure to test your logging statements.
760
761[[comp-logging-statements]]
762==== Component-specific logging statement macros
763
764There are available logging macros for components. They prepend a prefix
765including the component's name to the logging message.
766
767See <<logging-instrument-c-file-compcls>> and
768<<logging-instrument-h-file-compcls>> to learn how to be able to use the
769following macros.
770
771The component logging statement macros are named `+BT_COMP_LOG*()+`
772instead of `+BT_LOG*()+`:
773
774`+BT_COMP_LOGT("format string", ...)+`::
775 Component trace logging statement.
776
777`+BT_COMP_LOGD("format string", ...)+`::
778 Component debug logging statement.
779
780`+BT_COMP_LOGI("format string", ...)+`::
781 Component info logging statement.
782
783`+BT_COMP_LOGW("format string", ...)+`::
784 Component warning logging statement.
785
786`+BT_COMP_LOGE("format string", ...)+`::
787 Component error logging statement.
788
789`+BT_COMP_LOGF("format string", ...)+`::
790 Component fatal logging statement.
791
792`+BT_COMP_LOGT_STR("preformatted string")+`::
793 Component preformatted string trace logging statement.
794
795`+BT_COMP_LOGD_STR("preformatted string")+`::
796 Component preformatted string debug logging statement.
797
798`+BT_COMP_LOGI_STR("preformatted string")+`::
799 Component preformatted string info logging statement.
800
801`+BT_COMP_LOGW_STR("preformatted string")+`::
802 Component preformatted string warning logging statement.
803
804`+BT_COMP_LOGE_STR("preformatted string")+`::
805 Component preformatted string error logging statement.
806
807`+BT_COMP_LOGF_STR("preformatted string")+`::
808 Component preformatted string fatal logging statement.
809
810`+BT_COMP_LOGT_ERRNO("initial message", "format string", ...)+`::
811 Component `errno` string trace logging statement.
812
813`+BT_COMP_LOGD_ERRNO("initial message", "format string", ...)+`::
814 Component `errno` string debug logging statement.
815
816`+BT_COMP_LOGI_ERRNO("initial message", "format string", ...)+`::
817 Component `errno` string info logging statement.
818
819`+BT_COMP_LOGW_ERRNO("initial message", "format string", ...)+`::
820 Component `errno` string warning logging statement.
821
822`+BT_COMP_LOGE_ERRNO("initial message", "format string", ...)+`::
823 Component `errno` string error logging statement.
824
825`+BT_COMP_LOGF_ERRNO("initial message", "format string", ...)+`::
826 Component `errno` string fatal logging statement.
827
828`+BT_COMP_LOGT_MEM(data_ptr, data_size, "format string", ...)+`::
829 Component memory trace logging statement.
830
831`+BT_COMP_LOGD_MEM(data_ptr, data_size, "format string", ...)+`::
832 Component memory debug logging statement.
833
834`+BT_COMP_LOGI_MEM(data_ptr, data_size, "format string", ...)+`::
835 Component memory info logging statement.
836
837`+BT_COMP_LOGW_MEM(data_ptr, data_size, "format string", ...)+`::
838 Component memory warning logging statement.
839
840`+BT_COMP_LOGE_MEM(data_ptr, data_size, "format string", ...)+`::
841 Component memory error logging statement.
842
843`+BT_COMP_LOGF_MEM(data_ptr, data_size, "format string", ...)+`::
844 Component memory fatal logging statement.
845
846==== Conditional logging
847
848`+BT_LOG_IF(cond, statement)+`::
849 Execute `statement` only if `cond` is true.
850+
851Example:
852+
853--
854[source,c]
855----
856BT_LOG_IF(i < count / 2, BT_LOGD("Log this: i=%d", i));
857----
858--
859
860To check the <<build-time-log-level,build-time log level>>:
861
862[source,c]
863----
864#if BT_LOG_ENABLED_DEBUG
865...
866#endif
867----
868
869This tests if the _DEBUG_ level was enabled at build time. This means
870that the current, <<run-time-log-level,run-time log level>> _could_ be
871_DEBUG_, but it could also be higher. The rule of thumb is to use only
872logging statements at the same level in a `BT_LOG_ENABLED_*` conditional
873block.
874
875The available definitions for build-time conditions are:
876
877* `BT_LOG_ENABLED_TRACE`
878* `BT_LOG_ENABLED_DEBUG`
879* `BT_LOG_ENABLED_INFO`
880* `BT_LOG_ENABLED_WARNING`
881* `BT_LOG_ENABLED_ERROR`
882* `BT_LOG_ENABLED_FATAL`
883
884To check the current, <<run-time-log-level,run-time log level>>:
885
886[source,c]
887----
888if (BT_LOG_ON_DEBUG) {
889 ...
890}
891----
892
893This tests if the _DEBUG_ log level is dynamically turned on
894(implies that it's also enabled at build time). This check could have a
895noticeable impact on performance.
896
897The available definitions for run-time conditions are:
898
899* `BT_LOG_ON_TRACE`
900* `BT_LOG_ON_DEBUG`
901* `BT_LOG_ON_INFO`
902* `BT_LOG_ON_WARNING`
903* `BT_LOG_ON_ERROR`
904* `BT_LOG_ON_FATAL`
905
906Those macros check the module-specific log level symbol (defined by
907`BT_LOG_OUTPUT_LEVEL`).
908
909Never, ever write code which would be executed only to compute the
910fields of a logging statement outside a conditional logging scope,
911for example:
912
913[source,c]
914----
915int number = get_number_of_event_classes_with_property_x(...);
916BT_LOGD("Bla bla: number=%d", number);
917----
918
919Do this instead:
920
921[source,c]
922----
923if (BT_LOG_ON_DEBUG) {
924 int number = get_number_of_event_classes_with_property_x(...);
925 BT_LOGD("Bla bla: number=%d", number);
926}
927----
928
929Or even this:
930
931[source,c]
932----
933BT_LOGD("Bla bla: number=%d", get_number_of_event_classes_with_property_x(...));
934----
935
936=== Guides
937
938[[logging-instrument-c-file-gen]]
939==== Instrument a {c-cpp} source file (generic)
940
941To instrument a {c-cpp} source file (`.c`/`.cpp`):
942
943. At the top of the file, before the first `#include` line (if any),
944 define your file's <<choose-a-logging-tag,logging tag>> name:
945+
946--
947[source,c]
948----
949#define BT_LOG_TAG "SUBSYS/MY-MODULE/MY-FILE"
950----
951--
952
953. Below the line above, define the source file's log level expression,
954 `BT_LOG_OUTPUT_LEVEL`. This expression is evaluated for each
955 <<gen-logging-statements,logging statement>> to know the current
956 <<run-time-log-level,run-time log level>>.
957+
958Examples:
959+
960[source,c]
961----
962/* Global log level variable */
963#define BT_LOG_OUTPUT_LEVEL module_global_log_level
964----
965+
966[source,c]
967----
968/* Local log level variable; must exist where you use BT_LOG*() */
969#define BT_LOG_OUTPUT_LEVEL log_level
970----
971+
972[source,c]
973----
974/* Object's log level; `obj` must exist where you use BT_LOG*() */
975#define BT_LOG_OUTPUT_LEVEL (obj->log_level)
976----
977
978. Include `"logging/log.h"`:
979+
980[source,c]
981----
982#include "logging/log.h"
983----
984
985. In the file, instrument your code with the
986 <<gen-logging-statements,generic logging statement macros>>.
987
988[[logging-instrument-h-file-gen]]
989==== Instrument a {c-cpp} header file (generic)
990
991To instrument a {c-cpp} header file (`.h`/`.hpp`), if you have
992`static inline` functions in it:
993
994. Do not include `"logging/log.h"`!
995
996. Do one of:
997
998.. In the file, instrument your code with the
999 <<gen-logging-statements,generic logging statement macros>>, making
1000 each of them conditional to the existence of the macro you're using:
1001+
1002[source,c]
1003----
1004static inline
1005int some_function(int x)
1006{
1007 /* ... */
1008
1009#ifdef BT_LOGT
1010 BT_LOGT(...);
1011#endif
1012
1013 /* ... */
1014
1015#ifdef BT_LOGW_STR
1016 BT_LOGW_STR(...);
1017#endif
1018
1019 /* ... */
1020}
1021----
1022+
1023The {c-cpp} source files which include this header file determine if
1024logging is enabled or not for them, and if so, what is their
1025<<choose-a-logging-tag,logging tag>> and <<run-time-log-level,run-time
1026log level>> expression.
1027
1028.. Require that logging be enabled:
1029+
1030[source,c]
1031----
1032/* Protection: this file uses BT_LOG*() macros directly */
1033#ifndef BT_LOG_SUPPORTED
1034# error Please include "logging/log.h" before including this file.
1035#endif
1036----
1037+
1038Then, in the file, instrument your code with the
1039<<gen-logging-statements,generic logging statement macros>>.
1040
1041[[logging-instrument-c-file-lib]]
1042==== Instrument a library {c-cpp} source file
1043
1044To instrument a library {c-cpp} source file (`.c`/`.cpp`):
1045
1046. At the top of the file, before the first `#include` line (if any),
1047 define your file's <<choose-a-logging-tag,logging tag>> name (this
1048 tag must start with `LIB/`):
1049+
1050--
1051[source,c]
1052----
1053#define BT_LOG_TAG "LIB/THE-FILE"
1054----
1055--
1056
1057. Include `"lib/logging.h"`:
1058+
1059[source,c]
1060----
1061#include "lib/logging.h"
1062----
1063
1064. In the file, instrument your code with the
1065 <<lib-logging-statements,library logging statement macros>> or with
1066 the <<gen-logging-statements,generic logging statement macros>>.
1067
1068[[logging-instrument-h-file-lib]]
1069==== Instrument a library {c-cpp} header file
1070
1071To instrument a library {c-cpp} header file (`.h`/`.hpp`), if you have
1072`static inline` functions in it:
1073
1074. Do not include `"lib/logging.h"`!
1075
1076. Require that library logging be enabled:
1077+
1078[source,c]
1079----
1080/* Protection: this file uses BT_LIB_LOG*() macros directly */
1081#ifndef BT_LIB_LOG_SUPPORTED
1082# error Please include "lib/logging.h" before including this file.
1083#endif
1084----
1085
1086. In the file, instrument your code with the
1087 <<lib-logging-statements,library logging statement macros>> or with
1088 the <<gen-logging-statements,generic logging statement macros>>.
1089
1090[[logging-instrument-c-file-compcls]]
1091==== Instrument a component class {c-cpp} source file
1092
1093To instrument a component class {c-cpp} source file (`.c`/`.cpp`):
1094
1095. At the top of the file, before the first `#include` line (if any),
1096 define your file's <<choose-a-logging-tag,logging tag>> name (this tag
1097 must start with `PLUGIN/` followed by the component class identifier):
1098+
1099--
1100[source,c]
1101----
1102#define BT_LOG_TAG "PLUGIN/SRC.MY-PLUGIN.MY-SRC"
1103----
1104--
1105
1106. Below the line above, define the source file's log level expression,
1107 `BT_LOG_OUTPUT_LEVEL`. This expression is evaluated for each
1108 <<comp-logging-statements,logging statement>> to know the current
1109 <<run-time-log-level,run-time log level>>.
1110+
1111For a component class file, it is usually a member of a local component
1112private structure variable:
1113+
1114[source,c]
1115----
1116#define BT_LOG_OUTPUT_LEVEL (my_comp->log_level)
1117----
1118
1119. Below the line above, define `BT_COMP_LOG_SELF_COMP` to an expression
1120 which, evaluated in the context of the
1121 <<comp-logging-statements,logging statements>>, evaluates to the self
1122 component address (`+bt_self_component *+`) of the component.
1123+
1124This is usually a member of a local component private structure
1125variable:
1126+
1127[source,c]
1128----
1129#define BT_COMP_LOG_SELF_COMP (my_comp->self_comp)
1130----
1131
1132. Include `"logging/comp-logging.h"`:
1133+
1134[source,c]
1135----
1136#include "logging/comp-logging.h"
1137----
1138
1139. In the component initialization method, make sure to set the
1140 component private structure's log level member to the initial
1141 component's log level:
1142+
1143[source,c]
1144----
1145struct my_comp {
1146 bt_logging_level log_level;
1147 /* ... */
1148};
1149
1150bt_self_component_status my_comp_init(
1151 bt_self_component_source *self_comp_src,
1152 bt_value *params, void *init_method_data)
1153{
1154 struct my_comp *my_comp = g_new0(struct my_comp, 1);
1155 bt_self_component *self_comp =
1156 bt_self_component_source_as_self_component(self_comp_src);
1157 const bt_component *comp = bt_self_component_as_component(self_comp);
1158
1159 BT_ASSERT(my_comp);
1160 my_comp->log_level = bt_component_get_logging_level(comp);
1161
1162 /* ... */
1163}
1164----
1165
1166. In the file, instrument your code with the
1167 <<comp-logging-statements,component logging statement macros>>.
1168
1169[[logging-instrument-h-file-compcls]]
1170==== Instrument a component class {c-cpp} header file
1171
1172To instrument a component class {c-cpp} header file (`.h`/`.hpp`), if
1173you have `static inline` functions in it:
1174
1175. Do not include `"logging/comp-logging.h"`!
1176
1177. Require that component logging be enabled:
1178+
1179[source,c]
1180----
1181/* Protection: this file uses BT_COMP_LOG*() macros directly */
1182#ifndef BT_COMP_LOG_SUPPORTED
1183# error Please include "logging/comp-logging.h" before including this file.
1184#endif
1185----
1186
1187. In the file, instrument your code with the
1188 <<comp-logging-statements,component logging statement macros>>.
1189
1190[[choose-a-logging-tag]]
1191==== Choose a logging tag
1192
1193Each logging-enabled {c-cpp} source file must define `BT_LOG_TAG` to a
1194logging tag. A logging tag is a namespace to identify the logging
1195messages of this specific source file.
1196
1197In general, a logging tag name _must_ be only uppercase letters, digits,
1198and the `-`, `.`, and `/` characters.
1199
1200Use `/` to show the subsystem to source file hierarchy.
1201
1202For the {bt2} library, start with `LIB/`.
1203
1204For the CTF writer library, start with `CTF-WRITER/`.
1205
1206For component classes, use:
1207
1208[verse]
1209`PLUGIN/__CCTYPE__.__PNAME__.__CCNAME__[/__FILE__]`
1210
1211With:
1212
1213`__CCTYPE__`::
1214 Component class's type (`SRC`, `FLT`, or `SINK`).
1215
1216`__PNAME__`::
1217 Plugin's name.
1218
1219`__CCNAME__`::
1220 Component class's name.
1221
1222`__FILE__`::
1223 Additional information to specify the source file name or module.
1224
1225For plugins (files common to many component classes), use:
1226
1227[verse]
1228`PLUGIN/__PNAME__[/__FILE__]`
1229
1230With:
1231
1232`__PNAME__`::
1233 Plugin's name.
1234
1235`__FILE__`::
1236 Additional information to specify the source file name or module.
1237
1238[[choose-a-log-level]]
1239==== Choose a log level
1240
1241Choosing the appropriate level for your logging statement is very
1242important.
1243
1244[options="header,autowidth",cols="1,2,3a,4"]
1245|===
1246|Log level |Description |Use cases |Expected impact on performance
1247
1248|_FATAL_
1249|
1250The program, library, or plugin cannot continue to work in this
1251condition: it must be terminated immediately.
1252
1253A _FATAL_-level logging statement should always be followed by
1254`abort()`.
1255|
1256* Unexpected return values from system calls.
1257* Logic error in internal code, for example an unexpected value in a
1258 `switch` statement.
1259* Failed assertion (within `BT_ASSERT()`).
1260* Unsatisfied library precondition (within `BT_ASSERT_PRE()` or
1261 `BT_ASSERT_PRE_DEV()`).
1262* Unsatisfied library postcondition (within `BT_ASSERT_POST()` or
1263 `BT_ASSERT_POST_DEV()`).
1264|Almost none: always enabled.
1265
1266|_ERROR_
1267|
1268An important error which is somewhat not fatal, that is, the program,
1269library, or plugin can continue to work after this, but you judge that
1270it should be reported to the user.
1271
1272Usually, the program cannot recover from such an error, but it can at
1273least exit cleanly.
1274|
1275* Memory allocation errors.
1276* Wrong component initialization parameters.
1277* Corrupted, unrecoverable trace data.
1278* Failed to perform an operation which should work considering the
1279 implementation and the satisfied preconditions. For example, the
1280 failure to create an empty object (no parameters): most probably
1281 failed internally because of an allocation error.
1282* Almost any error in terminal elements: CLI and plugins.
1283|Almost none: always enabled.
1284
1285|_WARNING_
1286|
1287An error which still allows the execution to continue, but you judge
1288that it should be reported to the user.
1289
1290_WARNING_-level logging statements are for any error or weird action
1291that is directly or indirectly caused by the user, often through some
1292bad input data. For example, not having enough memory is considered
1293beyond the user's control, so we always log memory errors with an
1294_ERROR_ level (not _FATAL_ because we usually don't abort in this
1295condition).
1296|
1297* Missing data within something that is expected to have it, but there's
1298 an alternative.
1299* Invalid file, but recoverable/fixable.
1300|Almost none: always enabled.
1301
1302|_INFO_
1303|
1304Any useful information which a non-developer user would possibly
1305understand.
1306
1307Anything logged with this level must _not_ happen repetitively on the
1308fast path, that is, nothing related to each message, for example. This
1309level is used for sporadic and one-shot events.
1310|
1311* CLI or component configuration report.
1312* Successful plugin, component, or message iterator initialization.
1313* In the library: anything related to plugins, graphs, component
1314 classes, components, message iterators, connections, and ports which
1315 is not on the fast path.
1316* Successful connection to or disconnection from another system.
1317* An _optional_ subsystem cannot be loaded.
1318* An _optional_ field/datum cannot be found.
1319|
1320Very little: always enabled.
1321
1322|_DEBUG_
1323|
1324Something that only {bt2} developers would be interested into,
1325which can occur on the fast path, but not more often than once per
1326message.
1327
1328The _DEBUG_ level is the default <<build-time-log-level,build-time log
1329level>> as, since it's not _too_ verbose, the performance is similar to
1330an _INFO_ build.
1331|
1332* Object construction and destruction.
1333* Object recycling (except fields).
1334* Object copying (except fields and values).
1335* Object freezing (whatever the type, as freezing only occurs in
1336 developer mode).
1337* Object interruption.
1338* Calling user methods and logging the result.
1339* Setting object properties (except fields and values).
1340|
1341Noticeable, but not as much as the _TRACE_ level: could be executed
1342in production if you're going to need a thorough log for support
1343tickets without having to rebuild the project.
1344
1345|_TRACE_
1346|
1347Low-level debugging context information (anything that does not fit the
1348other log levels). More appropriate for tracing in general.
1349|
1350* Reference count change.
1351* Fast path, low level state machine's state change.
1352* Get or set an object's property.
1353* Object comparison's intermediate results.
1354|Huge: not executed in production.
1355|===
1356
1357[IMPORTANT]
1358--
1359Make sure not to use a _WARNING_ (or higher) log level when the
1360condition leading to the logging statement can occur under normal
1361circumstances.
1362
1363For example, a public function to get some object or
1364property from an object by name or key that fails to find the value is
1365not a warning scenario: the user could legitimately use this function to
1366check if the name/key exists in the object. In this case, use the
1367_TRACE_ level (or do not log at all).
1368--
1369
1370[[message]]
1371==== Write an appropriate message
1372
1373Follow those rules when you write a logging statement's message:
1374
1375* Use an English sentence which starts with a capital letter.
1376
1377* Start the sentence with the appropriate verb tense depending on the
1378 context. For example:
1379+
1380--
1381** Beginning of operation (present continuous): _Creating ..._,
1382 _Copying ..._, _Serializing ..._, _Freezing ..._, _Destroying ..._
1383** End of operation (simple past): _Created ..._, _Successfully created ..._,
1384 _Failed to create ..._, _Set ..._ (simple past of _to set_ which is
1385 also _set_)
1386--
1387+
1388For warning and error messages, you can start the message with _Cannot_
1389or _Failed to_ followed by a verb if it's appropriate.
1390
1391* Do not include the log level in the message itself. For example,
1392 do not start the message with _Error while_ or _Warning:_.
1393
1394* Do not put newlines, tabs, or other special characters in the message,
1395 unless you want to log a string with such characters. Note that
1396 multiline logging messages can be hard to parse, analyze, and filter,
1397 however, so prefer multiple logging statements over a single statement
1398 with newlines.
1399
1400* **If there are fields that your logging statement must record**,
1401 follow the message with `:` followed by a space, then with the list of
1402 fields (more about this below). If there are no fields, end the
1403 sentence with a period.
1404
1405The statement's fields _must_ be a comma-separated list of
1406`__name__=__value__` tokens. Keep `__name__` as simple as possible; use
1407kebab case if possible. If `__value__` is a non-alphanumeric string, put
1408it between double quotes (`"%s"` specifier). Always use the `PRId64` and
1409`PRIu64` specifiers to log an `int64_t` or an `uint64_t` value. Use `%d`
1410to log a boolean value.
1411
1412Example:
1413
1414 "Cannot read stream data for indexing: path=\"%s\", name=\"%s\", "
1415 "stream-id=%" PRIu64 ", stream-fd=%d, "
1416 "index=%" PRIu64 ", status=%s, is-mapped=%d"
1417
1418By following a standard format for the statement fields, it is easier to
1419use tools like https://www.elastic.co/products/logstash[Logstash] or
1420even https://www.splunk.com/[Splunk] to split fields and analyze logs.
1421
1422Prefer the following suffixes in field names:
1423
1424[options="header,autowidth"]
1425|===
1426|Field name suffix |Description |Format specifier
1427
1428|`-addr` |Memory address |`%p`
1429|`-fd` |File descriptor |`%d`
1430|`-fp` |File stream (`+FILE *+`) |`%p`
1431|`-id` |Object's ID |`%" PRIu64 "`
1432|`-index` |Index |`%" PRIu64 "`
1433|`-name` |Object's name |`\"%s\"`
1434|===
1435
1436=== Output
1437
1438The log is printed to the standard error stream. A log line contains the
1439time, the process and thread IDs, the <<log-levels,log level>>, the
1440<<choose-a-logging-tag,logging tag>>, the source's function name, file
1441name and line number, and the <<message,message>>.
1442
1443When {bt2} supports terminal color codes (depends on the
1444`BABELTRACE_TERM_COLOR` environment variable's value and what the
1445standard output and error streams are plugged into), _INFO_-level lines
1446are blue, _WARNING_-level lines are yellow, and _ERROR_-level and
1447_FATAL_-level lines are red.
1448
1449Log line example:
1450
1451----
145205-11 00:58:03.691 23402 23402 D VALUES bt_value_destroy@values.c:498 Destroying value: addr=0xb9c3eb0
1453----
1454
1455You can easily filter the log with `grep` or `ag`. For example, to keep
1456only the _DEBUG_-level logging messages that the `FIELD-CLASS` module
1457generates:
1458
1459----
1460$ babeltrace2 --log-level=D /path/to/trace |& ag 'D FIELD-CLASS'
1461----
1462
1463== Valgrind
1464
1465To use Valgrind on an application (for example, the CLI or a test) which
1466loads libbabeltrace2, use:
1467
1468----
1469$ G_SLICE=always-malloc G_DEBUG=gc-friendly PYTHONMALLOC=malloc \
1470 LIBBABELTRACE2_NO_DLCLOSE=1 valgrind --leak-check=full app
1471----
1472
1473`G_SLICE=always-malloc` and `G_DEBUG=gc-friendly` is for GLib and
1474`PYTHONMALLOC=malloc` is for the Python interpreter, if it is used by
1475the Python plugin provider (Valgrind will probably show a lot of errors
1476which originate from the Python interpreter anyway).
1477
1478`LIBBABELTRACE2_NO_DLCLOSE=1` makes libbabeltrace2 not close the shared
1479libraries (plugins) which it loads. You need this to see the appropriate
1480backtrace when Valgrind shows errors.
1481
1482== Testing
1483
1484[[test-env]]
1485=== Environment
1486
1487Running `make check` in the build directory (regardless of whether the build is
1488in-tree or out-of-tree) automatically sets up the appropriate environment for
1489tests to run in, so nothing more is needed.
1490
1491If building in-tree, you can run single tests from the tree directly:
1492
1493----
1494$ ./tests/plugins/sink.text.pretty/test_enum
1495----
1496
1497If building out-of-tree, you can get the appropriate environment by sourcing
1498the `tests/utils/env.sh` file residing in the build directory against which you
1499want to run tests.
1500
1501----
1502$ source /path/to/my/build/tests/utils/env.sh
1503$ ./tests/plugins/sink.text.pretty/test_enum
1504----
1505
1506==== Python
1507
1508You can use the `tests/utils/run_python_bt2` script to run any command
1509within an environment making the build's `bt2` Python package available.
1510
1511`run_python_bt2` uses <<test-env,`utils.sh`>> which needs to know the
1512build directory, so make sure you set the `BT_TESTS_BUILDDIR`
1513environment variable correctly _if you build out of tree_, for example:
1514
1515----
1516$ export BT_TESTS_BUILDDIR=/path/to/build/babeltrace/tests
1517----
1518
1519You can run any command which needs the `bt2` Python package through
1520`run_python_bt2`, for example:
1521
1522----
1523$ ./tests/utils/run_python_bt2 ipython3
1524----
1525
1526=== Report format
1527
1528All test scripts output the test results following the
1529https://testanything.org/[Test Anything Protocol] (TAP) format.
1530
1531The TAP format has two mechanisms to print additional information about
1532a test:
1533
1534* Print a line starting with `#` to the standard output.
1535+
1536This is usually done with the `diag()` C function or the `diag` shell
1537function.
1538
1539* Print to the standard error.
1540
1541=== Python bindings
1542
1543The `bt2` Python package tests are located in
1544`tests/bindings/python/bt2`.
1545
1546==== Python test runner
1547
1548`tests/utils/python/testrunner.py` is {bt2}'s Python test runner
1549which loads Python files containing unit tests, finds all the test
1550cases, and runs the tests, producing a TAP report.
1551
1552You can see the test runner command's help with:
1553
1554----
1555$ python3 ./tests/utils/python/testrunner.py --help
1556----
1557
1558By default, the test runner reports failing tests (TAP's `not{nbsp}ok`
1559line), but continues to run other tests. You can use the `--failfast`
1560option to make the test runner fail as soon as a test fails.
1561
1562==== Guides
1563
1564To run all the `bt2` Python package tests:
1565
1566* Run:
1567+
1568----
1569$ ./tests/utils/run_python_bt2 ./tests/bindings/python/bt2/test_python_bt2
1570----
1571+
1572or:
1573+
1574----
1575$ ./tests/utils/run_python_bt2 python3 ./tests/utils/python/testrunner.py \
1576 ./tests/bindings/python/bt2/ -p '*.py'
1577----
1578
1579To run **all the tests** in a test module (for example,
1580`test_value.py`):
1581
1582* Run:
1583+
1584----
1585$ ./tests/utils/run_python_bt2 python3 ./tests/utils/python/testrunner.py \
1586 ./tests/bindings/python/bt2 -t test_value
1587----
1588
1589To run a **specific test case** (for example, `RealValueTestCase` within
1590`test_value.py`):
1591
1592* Run:
1593+
1594----
1595$ ./tests/utils/run_python_bt2 python3 ./tests/utils/python/testrunner.py \
1596 ./tests/bindings/python/bt2/ -t test_value.RealValueTestCase
1597----
1598
1599To run a **specific test** (for example,
1600`RealValueTestCase.test_assign_pos_int` within `test_value.py`):
1601
1602* Run:
1603+
1604----
1605$ ./tests/utils/run_python_bt2 python3 ./tests/utils/python/testrunner.py \
1606 ./tests/bindings/python/bt2/ -t test_value.RealValueTestCase.test_assign_pos_int
1607----
1608
1609== {cpp} usage
1610
1611Some parts of {bt2} are written in {cpp}.
1612
1613This section shows what's important to know about {cpp} to contribute
1614to {bt2}.
1615
1616[IMPORTANT]
1617====
1618{bt2} only has {cpp} sources for _internal_ code.
1619
1620In other words, libbabeltrace2 _must_ expose a pure C99 API to preserve
1621ABI compatibility over time.
1622====
1623
1624=== Standard and dependencies
1625
1626The {bt2} project is configured to use the {cpp11} standard.
1627
1628{cpp11} makes it possible to build {bt2} with a broad range of
1629compilers, from GCC{nbsp}4.8 and Clang{nbsp}3.3.
1630
1631=== Automake/Libtool requirements
1632
1633To add a {cpp} source file to a part of the project, use the `.cpp`
1634extension and add it to the list of source files in `Makefile.am` as
1635usual.
1636
1637If a program or a shared library has a direct {cpp} source file, then
1638Libtool uses the {cpp} linker to create the result, dynamically
1639linking important runtime libraries such as libstdc++ and libgcc_s.
1640
1641Because a Libtool _convenience library_ is just an archive (`.a`), it's
1642_not_ dynamically linked to runtime libraries, even if one of its direct
1643sources is a {cpp} file. This means that for each program or shared
1644library named `my_target` in `Makefile.am` which is linked to a
1645convenience library having {cpp} sources (recursively), you _must_ do
1646one of:
1647
1648* Have at least one direct {cpp} source file in the
1649 `+*_my_target_SOURCES+` list.
1650
1651* Add:
1652+
1653----
1654nodist_EXTRA_my_target_SOURCES = dummy.cpp
1655----
1656+
1657See
1658https://www.gnu.org/software/automake/manual/automake.html#Libtool-Convenience-Libraries[Libtool
1659Convenience Libraries] to learn more.
1660
1661For a given program or library, you _cannot_ have a C{nbsp}file and a
1662{cpp}{nbsp}file having the same name, for example `list.c` and
1663`list.cpp`.
1664
1665=== Coding style
1666
1667==== Whitespaces, indentation, and line breaks
1668
1669All the project's {cpp} files follow the
1670https://clang.llvm.org/docs/ClangFormat.html[clang-format]
1671https://clang.llvm.org/docs/ClangFormatStyleOptions.html[style] of the
1672`.clang-format` file for whitespaces, indentation, and line breaks.
1673
1674You _must_ format modified and new {cpp} files with clang-format before
1675you create a contribution patch.
1676
1677You need clang-format{nbsp}15 to use the project's `.clang-format` file.
1678
1679To automatically format all the project's {cpp} files, run:
1680
1681----
1682$ ./tools/format-cpp
1683----
1684
1685Use the `FORMATTER` environment variable to override the default
1686formatter (`clang-format{nbsp}-i`):
1687
1688----
1689$ FORMATTER='clang-format-10 -i' ./tools/format-cpp
1690----
1691
1692==== Naming
1693
1694* Use camel case with a lowercase first letter for:
1695** Variable names: `size`, `objSize`.
1696** Function/method names: `size()`, `formatAndPrint()`.
1697
1698* Use camel case with an uppercase first letter for:
1699** Types: `Pistachio`, `NutManager`.
1700** Template parameters: `PlanetT`, `TotalSize`.
1701
1702* Use snake case with uppercase letters for:
1703** Definition/macro names: `MARK_AS_UNUSED()`, `SOME_FEATURE_EXISTS`.
1704** Enumerators: `Type::SIGNED_INT`, `Scope::FUNCTION`.
1705
1706* Use only lowercase letters and digits for namespaces: `mylib`, `bt2`.
1707
1708* Use the suffix `T` for type template parameters:
1709+
1710[source,cpp]
1711----
1712template <typename NameT, typename ItemT>
1713----
1714
1715* Name a template parameter pack `Args`.
1716+
1717[source,cpp]
1718----
1719template <typename NameT, typename... Args>
1720----
1721
1722* Use an underscore prefix for private and protected methods and member
1723 type names: `_tryConnect()`, `_NodeType`.
1724
1725* Use the prefix `_m` for private and protected member variable names:
1726 `_mLogger`, `_mSize`, `_mFieldClass`.
1727
1728* Name setters and getters like the property name, without `set` and
1729 `get` prefixes.
1730
1731* Use the `is` or `has` prefix, if possible, to name the functions which
1732 return `bool`.
1733
1734=== Coding convention
1735
1736In general, the project's contributors make an effort to follow,
1737for {cpp11} code:
1738
1739* The
1740 https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md[{cpp} Core Guidelines].
1741
1742* Scott Meyers's
1743 "`https://www.oreilly.com/library/view/effective-modern-c/9781491908419/[Effective Modern {cpp}]`".
1744
1745Here are a few important reminders:
1746
1747* Namespace your code.
1748
1749* Create one header/source file pair per class when possible.
1750+
1751For a class named `MyClass`, name the corresponding files `my-class.hpp`
1752and `my-class.cpp`.
1753
1754* When defining a class, put constructors as the first methods, whatever
1755 their access (public/protected/private), then the destructor, and then
1756 the rest.
1757
1758* Declare variables as close to where they are used as possible.
1759
1760* Use `auto` when possible.
1761
1762* Use `const` as much as possible, even for pointer
1763 (`+const char* const+`) and numeric values (`const unsigned int`)
1764 which never need to change.
1765
1766* Implement simple setters, getters, and one-liners in header files and
1767 everything else that's not a template in source files.
1768
1769* Make methods `const noexcept` or `const` as much as possible.
1770
1771* Make constructors `explicit` unless you really need an implicit
1772 constructor (which is rare).
1773
1774* Use `std::unique_ptr` to manage memory when possible.
1775+
1776However, use references (`+*my_unique_ptr+`) and raw pointers
1777(`+my_unique_ptr.get()+`) when not transferring ownership.
1778
1779* Use `nullptr`, not `NULL` nor 0.
1780
1781* Return by value (rvalue) instead of by output parameter (non-const
1782 lvalue reference), even complex objects, unless you can prove that the
1783 performance is improved when returning by parameter.
1784
1785* For a function parameter or a return value of which the type needs to
1786 be a reference or pointer, use:
1787+
1788If the value is mandatory:::
1789 A reference.
1790If the value is optional:::
1791 A raw pointer.
1792
1793* Don't use `+std::move()+` when you already have an rvalue, which
1794 means:
1795** Don't write `+return std::move(...);+` as this can interfere with
1796 RVO.
1797** Don't use `+std::move()+` with a function call
1798 (`+std::move(func())+`).
1799
1800* For each possible move/copy constructor or assignment operator, do one
1801 of:
1802** Write a custom one.
1803** Mark it as defaulted (`default`)
1804** Mark it as deleted (`delete`).
1805
1806* Use scoped enumerations (`+enum class+`).
1807
1808* Mark classes known to be final with the `final` keyword.
1809
1810* Use type aliases (`using`), not type definitions (`typedef`).
1811
1812* Use anonymous namespaces for local functions instead of `static`.
1813
1814* Don't pollute the global namespace:
1815** Don't use `using namespace xyz` anywhere.
1816** Use only namespace aliases in source files (`.cpp`), trying to
1817 use them in the smallest possible scope (function, or even smaller).
1818
1819* Return a structure with named members instead of a generic container
1820 such as `std::pair` or `std::tuple`.
1821
1822* When a class inherits a base class with virtual methods, use the
1823 `override` keyword to mark overridden virtual methods, and do not use
1824 the `virtual` keyword again.
1825
1826* Define overloaded operators only if their meaning is obvious,
1827 unsurprising, and consistent with the corresponding built-in
1828 operators.
1829+
1830For example, use `+|+` as a bitwise- or logical-or, not as a shell-style
1831pipe.
1832
1833* Use RAII wrappers when managing system resources or interacting with
1834 C{nbsp}libraries.
1835+
1836In other words, don't rely on ``goto``s and error labels to clean up as
1837you would do in{nbsp}C.
1838+
1839Use the RAII, Luke.
1840
1841* Throw an exception when there's an unexpected, exceptional condition,
1842 https://isocpp.org/wiki/faq/exceptions#ctors-can-throw[including from
1843 a constructor], instead of returning a status code.
1844
1845* Accept a by-value parameter and move it (when it's moveable) when you
1846 intend to copy it anyway.
1847+
1848You can do this with most STL containers.
1849+
1850Example:
1851+
1852[source,cpp]
1853----
1854void Obj::doSomething(std::string str)
1855{
1856 _mName = std::move(str);
1857 // ...
1858}
1859----
1860
1861.`baby.hpp`
1862====
1863This example shows a {cpp} header which follows the {bt2} {cpp} coding
1864convention.
1865
1866[source,cpp]
1867----
1868/*
1869 * SPDX-License-Identifier: MIT
1870 *
1871 * Copyright 2020 Harry Burnett <hburnett@reese.choco>
1872 */
1873
1874#ifndef BABELTRACE_BABY_HPP
1875#define BABELTRACE_BABY_HPP
1876
1877#include <string>
1878#include <unordered_set>
1879#include <utility>
1880
1881namespace life {
1882
1883class Toy;
1884
1885/*
1886 * A baby is a little human.
1887 */
1888class Baby : public Human
1889{
1890public:
1891 using Toys = std::unordered_set<Toy>;
1892
1893 enum class Gender
1894 {
1895 MALE,
1896 FEMALE,
1897 UNKNOWN,
1898 };
1899
1900 Baby() = default;
1901 explicit Baby(const Toys& toys);
1902 Baby(const Baby&) = delete;
1903 Baby(Baby&&) = delete;
1904 Baby& operator=(const Baby&) = delete;
1905 Baby& operator=(Baby&&) = delete;
1906
1907protected:
1908 explicit Baby(Gender initialGender = Gender::UNKNOWN);
1909
1910public:
1911 /*
1912 * Eats `weight` grams of food.
1913 */
1914 void eat(unsigned long weight);
1915
1916 /*
1917 * Sleeps for `duration` seconds.
1918 */
1919 void sleep(double duration);
1920
1921 /*
1922 * Sets this baby's name to `name`.
1923 */
1924 void name(std::string name)
1925 {
1926 _mName = std::move(name);
1927 }
1928
1929 /*
1930 * This baby's name.
1931 */
1932 const std::string& name() const noexcept
1933 {
1934 return _mName;
1935 }
1936
1937protected:
1938 void _addTeeth(unsigned long index);
1939 void _grow(double size) override;
1940
1941private:
1942 std::string _mName {"Paul"};
1943 Toys _mToys;
1944};
1945
1946} // namespace life
1947
1948#endif // BABELTRACE_BABY_HPP
1949----
1950====
This page took 0.048461 seconds and 4 git commands to generate.