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