Commit | Line | Data |
---|---|---|
cd4aac1e PP |
1 | // Render with Asciidoctor |
2 | ||
3 | = Babeltrace contributor's guide | |
f9ded0e0 | 4 | Jérémie Galarneau, Philippe Proulx |
cd4aac1e | 5 | v0.2, 19 June 2019 |
beb0fb75 PP |
6 | :toc: |
7 | :toclevels: 5 | |
8 | ||
beb0fb75 | 9 | |
f9ded0e0 PP |
10 | This is a partial contributor's guide for the |
11 | http://diamon.org/babeltrace[Babeltrace] project. If you have any | |
cd4aac1e 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 | |
cd4aac1e | 17 | == Babeltrace library |
f9ded0e0 | 18 | |
cd4aac1e | 19 | === Object reference counting and lifetime |
f9ded0e0 PP |
20 | |
21 | This section covers the rationale behind the design of Babeltrace's | |
cd4aac1e 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). | |
f9ded0e0 | 25 | |
cd4aac1e | 26 | Starting from Babeltrace 2.0, all publicly exposed objects inherit a |
f9ded0e0 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 | ||
cd4aac1e 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. | |
f9ded0e0 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 | ||
cd4aac1e | 40 | ==== The problem |
f9ded0e0 PP |
41 | |
42 | Let us consider a problematic case to illustrate the need for this | |
43 | distinction. | |
44 | ||
cd4aac1e 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). | |
f9ded0e0 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 | |
cd4aac1e 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. | |
f9ded0e0 PP |
60 | |
61 | Conversely, the user could also hold a reference to an event class and | |
cd4aac1e | 62 | retrieve its parent stream class. The trace class, in turn, can then be |
f9ded0e0 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 | ||
cd4aac1e | 76 | ==== The solution |
f9ded0e0 PP |
77 | |
78 | The scheme employed in Babeltrace to break this cycle consists in the | |
cd4aac1e | 79 | "children" holding _reverse component references_ to their parents. That |
56e18c4c 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 | |
cd4aac1e | 82 | their parent trace class. |
f9ded0e0 | 83 | |
cd4aac1e | 84 | On the other hand, parents hold _claiming aggregation references_ to |
f9ded0e0 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 | |
cd4aac1e 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 | |
f9ded0e0 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 | ||
cd4aac1e | 128 | ==== Example |
f9ded0e0 | 129 | |
cd4aac1e 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**. | |
f9ded0e0 PP |
135 | |
136 | image::doc/contributing-images/bt-ref01.png[] | |
137 | ||
cd4aac1e 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**. | |
f9ded0e0 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 | ||
cd4aac1e PP |
145 | Hence, at this point, the trace class's ownership is shared by |
146 | **User{nbsp}A** and **SC2**. | |
f9ded0e0 PP |
147 | |
148 | image::doc/contributing-images/bt-ref02.png[] | |
149 | ||
cd4aac1e 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. | |
f9ded0e0 | 154 | |
cd4aac1e | 155 | Note that SC2's reference count was incremented to 2. The trace class's |
f9ded0e0 PP |
156 | reference count remains unchanged. |
157 | ||
158 | image::doc/contributing-images/bt-ref03.png[] | |
159 | ||
cd4aac1e 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. | |
f9ded0e0 PP |
162 | |
163 | image::doc/contributing-images/bt-ref04.png[] | |
164 | ||
cd4aac1e 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. | |
f9ded0e0 PP |
169 | |
170 | image::doc/contributing-images/bt-ref05.png[] | |
171 | ||
cd4aac1e | 172 | If another object, **User{nbsp}B**, enters the picture and acquires a |
f9ded0e0 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 | ||
cd4aac1e 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**. | |
f9ded0e0 PP |
183 | |
184 | image::doc/contributing-images/bt-ref07.png[] | |
185 | ||
cd4aac1e | 186 | At some point, **User{nbsp}A** releases its reference on **EC3**. Since |
f9ded0e0 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 | ||
cd4aac1e 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**. | |
f9ded0e0 PP |
198 | |
199 | image::doc/contributing-images/bt-ref09.png[] | |
200 | ||
cd4aac1e 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. | |
f9ded0e0 | 204 | |
cd4aac1e 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. | |
f9ded0e0 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 | |
cd4aac1e | 226 | by the trace class. |
f9ded0e0 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 | ||
f9ded0e0 | 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 | |
cd4aac1e 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 | |
cd4aac1e PP |
247 | While <<choose-a-log-level,care must be taken>> when placing _DEBUG_ to |
248 | _FATAL_ logging statements, you should liberally instrument your | |
ef267d12 | 249 | Babeltrace module with _TRACE_ logging statements to help future you |
cd4aac1e | 250 | and other developers understand what's happening at run time. |
beb0fb75 PP |
251 | |
252 | ||
f9ded0e0 | 253 | === Logging API |
beb0fb75 PP |
254 | |
255 | The Babeltrace logging API is internal: it is not exposed to the users | |
cd4aac1e | 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 |
cd4aac1e | 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 | |
cd4aac1e 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 | |
cd4aac1e | 269 | library (`src/logging` directory). |
beb0fb75 PP |
270 | |
271 | ||
cd4aac1e | 272 | [[logging-headers]] |
f9ded0e0 | 273 | ==== Headers |
beb0fb75 PP |
274 | |
275 | The logging API headers are: | |
276 | ||
3fadfbc0 | 277 | `<babeltrace2/logging.h>`:: |
cd4aac1e | 278 | Public header which a library user can use to set and get |
a12f3d62 | 279 | libbabeltrace2's current log level. |
beb0fb75 | 280 | |
cd4aac1e | 281 | `"logging/log.h"`:: |
beb0fb75 | 282 | Internal, generic logging API which you can use in any Babeltrace |
cd4aac1e 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 | |
cd4aac1e 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 | |
cd4aac1e PP |
298 | `"plugins/comp-logging.h"`:: |
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 | |
cd4aac1e | 305 | [[log-levels]] |
f9ded0e0 | 306 | ==== Log levels |
beb0fb75 | 307 | |
cd4aac1e PP |
308 | The internal logging API offers the following log levels, in ascending |
309 | order of severity: | |
beb0fb75 | 310 | |
cd4aac1e 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 | ||
ef267d12 PP |
318 | |_TRACE_ |
319 | |`T` | |
320 | |`BT_LOG_TRACE` | |
321 | |`BT_LOGGING_LEVEL_TRACE` | |
cd4aac1e 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 | ||
333 | |_WARN_ | |
334 | |`W` | |
335 | |`BT_LOG_WARN` | |
336 | |`BT_LOGGING_LEVEL_WARN` | |
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 | |
cd4aac1e | 357 | See <<choose-a-log-level,how to decide which one to use>> below. |
beb0fb75 | 358 | |
cd4aac1e | 359 | There are two important log level expressions: |
beb0fb75 PP |
360 | |
361 | [[build-time-log-level]]Build-time, minimal log level:: | |
cd4aac1e 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 | |
f9ded0e0 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 | ---- | |
377 | $ BABELTRACE_MINIMAL_LOG_LEVEL=WARN ./configure | |
378 | ---- | |
379 | -- | |
380 | + | |
cd4aac1e 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 | |
dd22a91f PP |
383 | all the Babeltrace modules. You can't set it to `WARN`, `ERROR`, |
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:: | |
cd4aac1e 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 | + |
f9ded0e0 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 | |
cd4aac1e 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 | + |
a12f3d62 | 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 | |
cd4aac1e 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 | + |
cd4aac1e 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 | + |
cd4aac1e 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 | |
cd4aac1e 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 | |
cd4aac1e 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 | |
ef267d12 PP |
481 | `+BT_LOGT("format string", ...)+`:: |
482 | Generic trace logging statement. | |
beb0fb75 | 483 | |
cd4aac1e PP |
484 | `+BT_LOGD("format string", ...)+`:: |
485 | Generic debug logging statement. | |
beb0fb75 | 486 | |
cd4aac1e PP |
487 | `+BT_LOGI("format string", ...)+`:: |
488 | Generic info logging statement. | |
beb0fb75 | 489 | |
cd4aac1e PP |
490 | `+BT_LOGW("format string", ...)+`:: |
491 | Generic warning logging statement. | |
beb0fb75 | 492 | |
cd4aac1e PP |
493 | `+BT_LOGE("format string", ...)+`:: |
494 | Generic error logging statement. | |
beb0fb75 | 495 | |
cd4aac1e PP |
496 | `+BT_LOGF("format string", ...)+`:: |
497 | Generic fatal logging statement. | |
beb0fb75 | 498 | |
ef267d12 PP |
499 | `+BT_LOGT_STR("preformatted string")+`:: |
500 | Generic preformatted string trace logging statement. | |
beb0fb75 | 501 | |
cd4aac1e PP |
502 | `+BT_LOGD_STR("preformatted string")+`:: |
503 | Generic preformatted string debug logging statement. | |
beb0fb75 | 504 | |
cd4aac1e PP |
505 | `+BT_LOGI_STR("preformatted string")+`:: |
506 | Generic preformatted string info logging statement. | |
beb0fb75 | 507 | |
cd4aac1e PP |
508 | `+BT_LOGW_STR("preformatted string")+`:: |
509 | Generic preformatted string warning logging statement. | |
beb0fb75 | 510 | |
cd4aac1e PP |
511 | `+BT_LOGE_STR("preformatted string")+`:: |
512 | Generic preformatted string error logging statement. | |
beb0fb75 | 513 | |
cd4aac1e PP |
514 | `+BT_LOGF_STR("preformatted string")+`:: |
515 | Generic preformatted string fatal logging statement. | |
beb0fb75 | 516 | |
ef267d12 PP |
517 | `+BT_LOGT_MEM(data_ptr, data_size, "format string", ...)+`:: |
518 | Generic memory trace logging statement. | |
beb0fb75 | 519 | |
cd4aac1e PP |
520 | `+BT_LOGD_MEM(data_ptr, data_size, "format string", ...)+`:: |
521 | Generic memory debug logging statement. | |
b81626f9 | 522 | |
cd4aac1e PP |
523 | `+BT_LOGI_MEM(data_ptr, data_size, "format string", ...)+`:: |
524 | Generic memory info logging statement. | |
b81626f9 | 525 | |
cd4aac1e PP |
526 | `+BT_LOGW_MEM(data_ptr, data_size, "format string", ...)+`:: |
527 | Generic memory warning logging statement. | |
b81626f9 | 528 | |
cd4aac1e PP |
529 | `+BT_LOGE_MEM(data_ptr, data_size, "format string", ...)+`:: |
530 | Generic memory error logging statement. | |
b81626f9 | 531 | |
cd4aac1e PP |
532 | `+BT_LOGF_MEM(data_ptr, data_size, "format string", ...)+`:: |
533 | Generic memory fatal logging statement. | |
b81626f9 | 534 | |
ef267d12 PP |
535 | `+BT_LOGT_ERRNO("initial message", "format string", ...)+`:: |
536 | Generic `errno` string trace logging statement. | |
b81626f9 | 537 | |
cd4aac1e PP |
538 | `+BT_LOGD_ERRNO("initial message", "format string", ...)+`:: |
539 | Generic `errno` string debug logging statement. | |
beb0fb75 | 540 | |
cd4aac1e PP |
541 | `+BT_LOGI_ERRNO("initial message", "format string", ...)+`:: |
542 | Generic `errno` string info logging statement. | |
beb0fb75 | 543 | |
cd4aac1e PP |
544 | `+BT_LOGW_ERRNO("initial message", "format string", ...)+`:: |
545 | Generic `errno` string warning logging statement. | |
beb0fb75 | 546 | |
cd4aac1e PP |
547 | `+BT_LOGE_ERRNO("initial message", "format string", ...)+`:: |
548 | Generic `errno` string error logging statement. | |
beb0fb75 | 549 | |
cd4aac1e PP |
550 | `+BT_LOGF_ERRNO("initial message", "format string", ...)+`:: |
551 | Generic `errno` string fatal logging statement. | |
beb0fb75 | 552 | |
cd4aac1e 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 | ||
ef267d12 PP |
568 | `+BT_LIB_LOGT("format string", ...)+`:: |
569 | Library trace logging statement. | |
cd4aac1e 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 | ||
3cd4c495 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 | ||
cd4aac1e 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 | |
634 | |`+struct bt_field_class *+` | |
635 | ||
636 | |`f` | |
637 | |Trace IR field | |
638 | |`+struct bt_field *+` | |
639 | ||
640 | |`P` | |
641 | |Trace IR field path | |
642 | |`+struct bt_field_path *+` | |
643 | ||
644 | |`E` | |
645 | |Trace IR event class | |
646 | |`+struct bt_event_class *+` | |
647 | ||
648 | |`e` | |
649 | |Trace IR event | |
650 | |`+struct bt_event *+` | |
651 | ||
652 | |`S` | |
653 | |Trace IR stream class. | |
654 | |`+struct bt_stream_class *+` | |
655 | ||
656 | |`s` | |
657 | |Trace IR stream | |
658 | |`+struct bt_stream *+` | |
659 | ||
660 | |`a` | |
661 | |Trace IR packet | |
662 | |`+struct bt_packet *+` | |
663 | ||
664 | |`T` | |
665 | |Trace IR trace class | |
666 | |`+struct bt_trace_class *+` | |
667 | ||
668 | |`t` | |
669 | |Trace IR trace | |
670 | |`+struct bt_trace *+` | |
671 | ||
672 | |`K` | |
673 | |Trace IR clock class | |
674 | |`+struct bt_clock_class *+` | |
675 | ||
676 | |`k` | |
677 | |Trace IR clock snapshot | |
678 | |`+struct bt_clock_snapshot *+` | |
679 | ||
680 | |`v` | |
681 | |Value object | |
682 | |`+struct bt_value *+` | |
683 | ||
684 | |`n` | |
685 | |Message | |
686 | |`+struct bt_message *+` | |
687 | ||
688 | |`i` | |
689 | |Message iterator | |
690 | |`struct bt_message_iterator *` | |
691 | ||
692 | |`C` | |
693 | |Component class | |
694 | |`struct bt_component_class *` | |
695 | ||
696 | |`c` | |
697 | |Component | |
698 | |`+struct bt_component *+` | |
699 | ||
700 | |`p` | |
701 | |Port | |
702 | |`+struct bt_port *+` | |
703 | ||
704 | |`x` | |
705 | |Connection | |
706 | |`+struct bt_connection *+` | |
707 | ||
708 | |`g` | |
709 | |Graph | |
710 | |`+struct bt_graph *+` | |
711 | ||
712 | |`l` | |
713 | |Plugin | |
714 | |`const struct bt_plugin *` | |
715 | ||
553c4bab PP |
716 | |`r` |
717 | |Error cause | |
718 | |`const struct bt_error_cause *` | |
719 | ||
cd4aac1e PP |
720 | |`o` |
721 | |Object pool | |
722 | |`+struct bt_object_pool *+` | |
723 | ||
724 | |`O` | |
725 | |Object | |
726 | |`+struct bt_object *+` | |
727 | |=== | |
728 | ||
729 | Conversion specifier examples: | |
730 | ||
731 | * `%!f` | |
732 | * `%![my-event-]+e` | |
733 | * `%!t` | |
734 | * `%!+F` | |
735 | ||
736 | The ``, `` string (comma and space) is printed between individual | |
737 | fields, but **not after the last one**. Therefore, you must put this | |
738 | separator in the format string between two conversion specifiers, for | |
739 | example: | |
740 | ||
741 | [source,c] | |
742 | ---- | |
743 | BT_LIB_LOGW("Message: count=%u, %!E, %!+K", count, event_class, clock_class); | |
744 | ---- | |
745 | ||
746 | Example with a custom prefix: | |
747 | ||
748 | [source,c] | |
749 | ---- | |
750 | BT_LIB_LOGI("Some message: %![ec-a-]e, %![ec-b-]+e", ec_a, ec_b); | |
751 | ---- | |
752 | ||
753 | It is safe to pass `NULL` as any Babeltrace object parameter: the macros | |
754 | only print its null address. | |
755 | ||
756 | WARNING: Build-time `printf()` format checks are disabled for the | |
757 | `+BT_LIB_LOG*()+` macros because there are custom conversion specifiers, | |
758 | so make sure to test your logging statements. | |
759 | ||
760 | ||
761 | [[comp-logging-statements]] | |
762 | ==== Component-specific logging statement macros | |
763 | ||
764 | There are available logging macros for components. They prepend a prefix | |
765 | including the component's name to the logging message. | |
766 | ||
767 | See <<logging-instrument-c-file-compcls,Instrument a component class C | |
768 | source file>> and <<logging-instrument-h-file-compcls,Instrument a | |
769 | component class C header file>> to learn how to be able to use the | |
770 | following macros. | |
771 | ||
772 | The component logging statement macros are named `+BT_COMP_LOG*()+` | |
773 | instead of `+BT_LOG*()+`: | |
774 | ||
ef267d12 PP |
775 | `+BT_COMP_LOGT("format string", ...)+`:: |
776 | Component trace logging statement. | |
cd4aac1e PP |
777 | |
778 | `+BT_COMP_LOGD("format string", ...)+`:: | |
779 | Component debug logging statement. | |
780 | ||
781 | `+BT_COMP_LOGI("format string", ...)+`:: | |
782 | Component info logging statement. | |
783 | ||
784 | `+BT_COMP_LOGW("format string", ...)+`:: | |
785 | Component warning logging statement. | |
786 | ||
787 | `+BT_COMP_LOGE("format string", ...)+`:: | |
788 | Component error logging statement. | |
789 | ||
790 | `+BT_COMP_LOGF("format string", ...)+`:: | |
791 | Component fatal logging statement. | |
792 | ||
ef267d12 PP |
793 | `+BT_COMP_LOGT_STR("preformatted string")+`:: |
794 | Component preformatted string trace logging statement. | |
cd4aac1e PP |
795 | |
796 | `+BT_COMP_LOGD_STR("preformatted string")+`:: | |
797 | Component preformatted string debug logging statement. | |
798 | ||
799 | `+BT_COMP_LOGI_STR("preformatted string")+`:: | |
800 | Component preformatted string info logging statement. | |
801 | ||
802 | `+BT_COMP_LOGW_STR("preformatted string")+`:: | |
803 | Component preformatted string warning logging statement. | |
804 | ||
805 | `+BT_COMP_LOGE_STR("preformatted string")+`:: | |
806 | Component preformatted string error logging statement. | |
807 | ||
808 | `+BT_COMP_LOGF_STR("preformatted string")+`:: | |
809 | Component preformatted string fatal logging statement. | |
810 | ||
ef267d12 PP |
811 | `+BT_COMP_LOGT_ERRNO("initial message", "format string", ...)+`:: |
812 | Component `errno` string trace logging statement. | |
cd4aac1e PP |
813 | |
814 | `+BT_COMP_LOGD_ERRNO("initial message", "format string", ...)+`:: | |
815 | Component `errno` string debug logging statement. | |
816 | ||
817 | `+BT_COMP_LOGI_ERRNO("initial message", "format string", ...)+`:: | |
818 | Component `errno` string info logging statement. | |
819 | ||
820 | `+BT_COMP_LOGW_ERRNO("initial message", "format string", ...)+`:: | |
821 | Component `errno` string warning logging statement. | |
822 | ||
823 | `+BT_COMP_LOGE_ERRNO("initial message", "format string", ...)+`:: | |
824 | Component `errno` string error logging statement. | |
825 | ||
826 | `+BT_COMP_LOGF_ERRNO("initial message", "format string", ...)+`:: | |
827 | Component `errno` string fatal logging statement. | |
828 | ||
ef267d12 PP |
829 | `+BT_COMP_LOGT_MEM(data_ptr, data_size, "format string", ...)+`:: |
830 | Component memory trace logging statement. | |
cd4aac1e PP |
831 | |
832 | `+BT_COMP_LOGD_MEM(data_ptr, data_size, "format string", ...)+`:: | |
833 | Component memory debug logging statement. | |
834 | ||
835 | `+BT_COMP_LOGI_MEM(data_ptr, data_size, "format string", ...)+`:: | |
836 | Component memory info logging statement. | |
837 | ||
838 | `+BT_COMP_LOGW_MEM(data_ptr, data_size, "format string", ...)+`:: | |
839 | Component memory warning logging statement. | |
840 | ||
841 | `+BT_COMP_LOGE_MEM(data_ptr, data_size, "format string", ...)+`:: | |
842 | Component memory error logging statement. | |
843 | ||
844 | `+BT_COMP_LOGF_MEM(data_ptr, data_size, "format string", ...)+`:: | |
845 | Component memory fatal logging statement. | |
beb0fb75 PP |
846 | |
847 | ||
f9ded0e0 | 848 | ==== Conditional logging |
beb0fb75 | 849 | |
cd4aac1e | 850 | `+BT_LOG_IF(cond, statement)+`:: |
beb0fb75 PP |
851 | Execute `statement` only if `cond` is true. |
852 | + | |
853 | Example: | |
854 | + | |
855 | -- | |
856 | [source,c] | |
857 | ---- | |
858 | BT_LOG_IF(i < count / 2, BT_LOGD("Log this: i=%d", i)); | |
859 | ---- | |
860 | -- | |
861 | ||
862 | To check the <<build-time-log-level,build-time log level>>: | |
863 | ||
864 | [source,c] | |
865 | ---- | |
866 | #if BT_LOG_ENABLED_DEBUG | |
867 | ... | |
868 | #endif | |
869 | ---- | |
870 | ||
cd4aac1e PP |
871 | This tests if the _DEBUG_ level was enabled at build time. This means |
872 | that the current, <<run-time-log-level,run-time log level>> _could_ be | |
f9ded0e0 PP |
873 | _DEBUG_, but it could also be higher. The rule of thumb is to use only |
874 | logging statements at the same level in a `BT_LOG_ENABLED_*` conditional | |
875 | block. | |
beb0fb75 PP |
876 | |
877 | The available definitions for build-time conditions are: | |
878 | ||
ef267d12 | 879 | * `BT_LOG_ENABLED_TRACE` |
beb0fb75 PP |
880 | * `BT_LOG_ENABLED_DEBUG` |
881 | * `BT_LOG_ENABLED_INFO` | |
882 | * `BT_LOG_ENABLED_WARN` | |
883 | * `BT_LOG_ENABLED_ERROR` | |
884 | * `BT_LOG_ENABLED_FATAL` | |
885 | ||
886 | To check the current, <<run-time-log-level,run-time log level>>: | |
887 | ||
888 | [source,c] | |
889 | ---- | |
890 | if (BT_LOG_ON_DEBUG) { | |
891 | ... | |
892 | } | |
893 | ---- | |
894 | ||
895 | This tests if the _DEBUG_ log level is dynamically turned on | |
cd4aac1e | 896 | (implies that it's also enabled at build time). This check could have a |
beb0fb75 PP |
897 | noticeable impact on performance. |
898 | ||
899 | The available definitions for run-time conditions are: | |
900 | ||
ef267d12 | 901 | * `BT_LOG_ON_TRACE` |
beb0fb75 PP |
902 | * `BT_LOG_ON_DEBUG` |
903 | * `BT_LOG_ON_INFO` | |
904 | * `BT_LOG_ON_WARN` | |
905 | * `BT_LOG_ON_ERROR` | |
906 | * `BT_LOG_ON_FATAL` | |
907 | ||
cd4aac1e PP |
908 | Those macros check the module-specific log level symbol (defined by |
909 | `BT_LOG_OUTPUT_LEVEL`). | |
beb0fb75 PP |
910 | |
911 | Never, ever write code which would be executed only to compute the | |
912 | fields of a logging statement outside a conditional logging scope, | |
913 | for example: | |
914 | ||
915 | [source,c] | |
916 | ---- | |
917 | int number = get_number_of_event_classes_with_property_x(...); | |
918 | BT_LOGD("Bla bla: number=%d", number); | |
919 | ---- | |
920 | ||
921 | Do this instead: | |
922 | ||
923 | [source,c] | |
924 | ---- | |
925 | if (BT_LOG_ON_DEBUG) { | |
926 | int number = get_number_of_event_classes_with_property_x(...); | |
927 | BT_LOGD("Bla bla: number=%d", number); | |
928 | } | |
929 | ---- | |
930 | ||
931 | Or even this: | |
932 | ||
933 | [source,c] | |
934 | ---- | |
935 | BT_LOGD("Bla bla: number=%d", get_number_of_event_classes_with_property_x(...)); | |
936 | ---- | |
937 | ||
938 | ||
cd4aac1e | 939 | === Guides |
beb0fb75 | 940 | |
cd4aac1e PP |
941 | [[logging-instrument-c-file-gen]] |
942 | ==== Instrument a C source file (generic) | |
beb0fb75 | 943 | |
cd4aac1e PP |
944 | To instrument a C source file (`.c`): |
945 | ||
946 | . At the top of the file, before the first `#include` line (if any), | |
947 | define your file's <<choose-a-logging-tag,logging tag>> name: | |
4a41523d PP |
948 | + |
949 | -- | |
950 | [source,c] | |
951 | ---- | |
cd4aac1e | 952 | #define BT_LOG_TAG "SUBSYS/MY-MODULE/MY-FILE" |
4a41523d PP |
953 | ---- |
954 | -- | |
cd4aac1e PP |
955 | |
956 | . Below the line above, define the source file's log level expression, | |
957 | `BT_LOG_OUTPUT_LEVEL`. This expression is evaluated for each | |
958 | <<gen-logging-statements,logging statement>> to know the current | |
959 | <<run-time-log-level,run-time log level>>. | |
960 | + | |
961 | Examples: | |
962 | + | |
963 | [source,c] | |
964 | ---- | |
965 | /* Global log level variable */ | |
966 | #define BT_LOG_OUTPUT_LEVEL module_global_log_level | |
967 | ---- | |
4a41523d | 968 | + |
cd4aac1e PP |
969 | [source,c] |
970 | ---- | |
971 | /* Local log level variable; must exist where you use BT_LOG*() */ | |
972 | #define BT_LOG_OUTPUT_LEVEL log_level | |
973 | ---- | |
974 | + | |
975 | [source,c] | |
976 | ---- | |
977 | /* Object's log level; `obj` must exist where you use BT_LOG*() */ | |
978 | #define BT_LOG_OUTPUT_LEVEL (obj->log_level) | |
979 | ---- | |
4a41523d | 980 | |
cd4aac1e | 981 | . Include `"logging/log.h"`: |
4a41523d | 982 | + |
beb0fb75 PP |
983 | [source,c] |
984 | ---- | |
578e048b | 985 | #include "logging/log.h" |
cd4aac1e | 986 | ---- |
4a41523d | 987 | |
cd4aac1e PP |
988 | . In the file, instrument your code with the |
989 | <<gen-logging-statements,generic logging statement macros>>. | |
4a41523d | 990 | |
cd4aac1e PP |
991 | |
992 | [[logging-instrument-h-file-gen]] | |
993 | ==== Instrument a C header file (generic) | |
994 | ||
995 | To instrument a C header file (`.h`), if you have `static inline` | |
996 | functions in it: | |
997 | ||
998 | . Do not include `"logging/log.h"`! | |
999 | ||
1000 | . Do one of: | |
1001 | ||
1002 | .. In the file, instrument your code with the | |
1003 | <<gen-logging-statements,generic logging statement macros>>, making | |
1004 | each of them conditional to the existence of the macro you're using: | |
4a41523d | 1005 | + |
cd4aac1e PP |
1006 | [source,c] |
1007 | ---- | |
1008 | static inline | |
1009 | int some_function(int x) | |
1010 | { | |
1011 | /* ... */ | |
4a41523d | 1012 | |
ef267d12 PP |
1013 | #ifdef BT_LOGT |
1014 | BT_LOGT(...); | |
cd4aac1e | 1015 | #endif |
beb0fb75 | 1016 | |
cd4aac1e | 1017 | /* ... */ |
6470c171 | 1018 | |
cd4aac1e PP |
1019 | #ifdef BT_LOGW_STR |
1020 | BT_LOGW_STR(...); | |
1021 | #endif | |
f9ded0e0 | 1022 | |
cd4aac1e PP |
1023 | /* ... */ |
1024 | } | |
1025 | ---- | |
1026 | + | |
1027 | The C source files which include this header file determine if logging | |
1028 | is enabled or not for them, and if so, what is their | |
1029 | <<choose-a-logging-tag,logging tag>> and <<run-time-log-level,run-time | |
1030 | log level>> expression. | |
f9ded0e0 | 1031 | |
cd4aac1e PP |
1032 | .. Require that logging be enabled: |
1033 | + | |
1034 | [source,c] | |
1035 | ---- | |
1036 | /* Protection: this file uses BT_LOG*() macros directly */ | |
1037 | #ifndef BT_LOG_SUPPORTED | |
1038 | # error Please include "logging/log.h" before including this file. | |
1039 | #endif | |
1040 | ---- | |
1041 | + | |
1042 | Then, in the file, instrument your code with the | |
1043 | <<gen-logging-statements,generic logging statement macros>>. | |
1044 | ||
1045 | ||
1046 | [[logging-instrument-c-file-lib]] | |
1047 | ==== Instrument a library C source file | |
1048 | ||
1049 | To instrument a library C source file (`.c`): | |
4a41523d PP |
1050 | |
1051 | . At the top of the file, before the first `#include` line (if any), | |
cd4aac1e PP |
1052 | define your file's <<choose-a-logging-tag,logging tag>> name (this |
1053 | tag must start with `LIB/`): | |
4a41523d PP |
1054 | + |
1055 | -- | |
1056 | [source,c] | |
1057 | ---- | |
cd4aac1e | 1058 | #define BT_LOG_TAG "LIB/THE-FILE" |
4a41523d PP |
1059 | ---- |
1060 | -- | |
cd4aac1e PP |
1061 | |
1062 | . Include `"lib/logging.h"`: | |
4a41523d | 1063 | + |
cd4aac1e PP |
1064 | [source,c] |
1065 | ---- | |
1066 | #include "lib/logging.h" | |
1067 | ---- | |
4a41523d | 1068 | |
cd4aac1e PP |
1069 | . In the file, instrument your code with the |
1070 | <<lib-logging-statements,library logging statement macros>> or with | |
1071 | the <<gen-logging-statements,generic logging statement macros>>. | |
4a41523d | 1072 | |
f9ded0e0 | 1073 | |
cd4aac1e PP |
1074 | [[logging-instrument-h-file-lib]] |
1075 | ==== Instrument a library C header file | |
1076 | ||
1077 | To instrument a library C header file (`.h`), if you have `static | |
1078 | inline` functions in it: | |
1079 | ||
1080 | . Do not include `"lib/logging.h"`! | |
1081 | ||
1082 | . Require that library logging be enabled: | |
1083 | + | |
1084 | [source,c] | |
1085 | ---- | |
1086 | /* Protection: this file uses BT_LIB_LOG*() macros directly */ | |
1087 | #ifndef BT_LIB_LOG_SUPPORTED | |
1088 | # error Please include "lib/logging.h" before including this file. | |
1089 | #endif | |
1090 | ---- | |
1091 | ||
1092 | . In the file, instrument your code with the | |
1093 | <<lib-logging-statements,library logging statement macros>> or with | |
1094 | the <<gen-logging-statements,generic logging statement macros>>. | |
f9ded0e0 | 1095 | |
4a41523d | 1096 | |
cd4aac1e PP |
1097 | [[logging-instrument-c-file-compcls]] |
1098 | ==== Instrument a component class C source file | |
1099 | ||
1100 | To instrument a component class C source file (`.c`): | |
1101 | ||
1102 | . At the top of the file, before the first `#include` line (if any), | |
1103 | define your file's <<choose-a-logging-tag,logging tag>> name (this tag | |
1104 | must start with `PLUGIN/` followed by the component class identifier): | |
4a41523d PP |
1105 | + |
1106 | -- | |
1107 | [source,c] | |
1108 | ---- | |
cd4aac1e PP |
1109 | #define BT_LOG_TAG "PLUGIN/SRC.MY-PLUGIN.MY-SRC" |
1110 | ---- | |
1111 | -- | |
4a41523d | 1112 | |
cd4aac1e PP |
1113 | . Below the line above, define the source file's log level expression, |
1114 | `BT_LOG_OUTPUT_LEVEL`. This expression is evaluated for each | |
1115 | <<comp-logging-statements,logging statement>> to know the current | |
1116 | <<run-time-log-level,run-time log level>>. | |
1117 | + | |
1118 | For a component class file, it is usually a member of a local component | |
1119 | private structure variable: | |
1120 | + | |
1121 | [source,c] | |
1122 | ---- | |
1123 | #define BT_LOG_OUTPUT_LEVEL (my_comp->log_level) | |
1124 | ---- | |
4a41523d | 1125 | |
cd4aac1e PP |
1126 | . Below the line above, define `BT_COMP_LOG_SELF_COMP` to an expression |
1127 | which, evaluated in the context of the | |
1128 | <<comp-logging-statements,logging statements>>, evaluates to the self | |
1129 | component address (`+bt_self_component *+`) of the component. | |
1130 | + | |
1131 | This is usually a member of a local component private structure | |
1132 | variable: | |
1133 | + | |
1134 | [source,c] | |
1135 | ---- | |
1136 | #define BT_COMP_LOG_SELF_COMP (my_comp->self_comp) | |
1137 | ---- | |
1138 | ||
1139 | . Include `"plugins/comp-logging.h"`: | |
1140 | + | |
1141 | [source,c] | |
1142 | ---- | |
1143 | #include "plugins/comp-logging.h" | |
1144 | ---- | |
1145 | ||
1146 | . In the component initialization method, make sure to set the | |
1147 | component private structure's log level member to the initial | |
1148 | component's log level: | |
1149 | + | |
1150 | [source,c] | |
1151 | ---- | |
1152 | struct my_comp { | |
1153 | bt_logging_level log_level; | |
4a41523d | 1154 | /* ... */ |
cd4aac1e | 1155 | }; |
4a41523d | 1156 | |
cd4aac1e PP |
1157 | BT_HIDDEN |
1158 | bt_self_component_status my_comp_init( | |
1159 | bt_self_component_source *self_comp_src, | |
1160 | bt_value *params, void *init_method_data) | |
1161 | { | |
1162 | struct my_comp *my_comp = g_new0(struct my_comp, 1); | |
1163 | bt_self_component *self_comp = | |
1164 | bt_self_component_source_as_self_component(self_comp_src); | |
1165 | const bt_component *comp = bt_self_component_as_component(self_comp); | |
1166 | ||
1167 | BT_ASSERT(my_comp); | |
1168 | my_comp->log_level = bt_component_get_logging_level(comp); | |
4a41523d PP |
1169 | |
1170 | /* ... */ | |
1171 | } | |
1172 | ---- | |
cd4aac1e PP |
1173 | |
1174 | . In the file, instrument your code with the | |
1175 | <<comp-logging-statements,component logging statement macros>>. | |
1176 | ||
1177 | ||
1178 | [[logging-instrument-h-file-compcls]] | |
1179 | ==== Instrument a component class C header file | |
1180 | ||
1181 | To instrument a component class C header file (`.h`), if you have | |
1182 | `static inline` functions in it: | |
1183 | ||
1184 | . Do not include `"plugins/comp-logging.h"`! | |
1185 | ||
1186 | . Require that component logging be enabled: | |
4a41523d | 1187 | + |
cd4aac1e PP |
1188 | [source,c] |
1189 | ---- | |
1190 | /* Protection: this file uses BT_COMP_LOG*() macros directly */ | |
1191 | #ifndef BT_COMP_LOG_SUPPORTED | |
1192 | # error Please include "plugins/comp-logging.h" before including this file. | |
1193 | #endif | |
1194 | ---- | |
1195 | ||
1196 | . In the file, instrument your code with the | |
1197 | <<comp-logging-statements,component logging statement macros>>. | |
1198 | ||
1199 | ||
1200 | [[choose-a-logging-tag]] | |
1201 | ==== Choose a logging tag | |
beb0fb75 | 1202 | |
cd4aac1e PP |
1203 | Each logging-enabled C source file must define `BT_LOG_TAG` to a logging |
1204 | tag. A logging tag is a namespace to identify the logging messages of | |
1205 | this specific source file. | |
beb0fb75 | 1206 | |
cd4aac1e PP |
1207 | In general, a logging tag name _must_ be only uppercase letters, digits, |
1208 | and the `-`, `.`, and `/` characters. | |
beb0fb75 | 1209 | |
cd4aac1e PP |
1210 | Use `/` to show the subsystem to source file hierarchy. |
1211 | ||
1212 | For the Babeltrace library, start with `LIB/`. | |
1213 | ||
1214 | For the CTF writer library, start with `CTF-WRITER/`. | |
1215 | ||
1216 | For component classes, use: | |
beb0fb75 | 1217 | |
93841983 | 1218 | [verse] |
cd4aac1e PP |
1219 | `PLUGIN/__CCTYPE__.__PNAME__.__CCNAME__[/__FILE__]` |
1220 | ||
1221 | With: | |
1222 | ||
1223 | `__CCTYPE__`:: | |
1224 | Component class's type (`SRC`, `FLT`, or `SINK`). | |
beb0fb75 | 1225 | |
cd4aac1e | 1226 | `__PNAME__`:: |
93841983 | 1227 | Plugin's name. |
beb0fb75 | 1228 | |
cd4aac1e | 1229 | `__CCNAME__`:: |
93841983 | 1230 | Component class's name. |
beb0fb75 | 1231 | |
cd4aac1e | 1232 | `__FILE__`:: |
93841983 | 1233 | Additional information to specify the source file name or module. |
beb0fb75 | 1234 | |
cd4aac1e | 1235 | For plugins (files common to many component classes), use: |
beb0fb75 | 1236 | |
cd4aac1e PP |
1237 | [verse] |
1238 | `PLUGIN/__PNAME__[/__FILE__]` | |
beb0fb75 | 1239 | |
cd4aac1e | 1240 | With: |
beb0fb75 | 1241 | |
cd4aac1e PP |
1242 | `__PNAME__`:: |
1243 | Plugin's name. | |
1244 | ||
1245 | `__FILE__`:: | |
1246 | Additional information to specify the source file name or module. | |
1247 | ||
1248 | ||
1249 | [[choose-a-log-level]] | |
1250 | ==== Choose a log level | |
beb0fb75 PP |
1251 | |
1252 | Choosing the appropriate level for your logging statement is very | |
1253 | important. | |
1254 | ||
cd4aac1e | 1255 | [options="header,autowidth",cols="1,2,3a,4"] |
beb0fb75 | 1256 | |=== |
cd4aac1e | 1257 | |Log level |Description |Use cases |Expected impact on performance |
beb0fb75 PP |
1258 | |
1259 | |_FATAL_ | |
cd4aac1e PP |
1260 | | |
1261 | The program, library, or plugin cannot continue to work in this | |
beb0fb75 PP |
1262 | condition: it must be terminated immediately. |
1263 | ||
b4b9064d | 1264 | A _FATAL_-level logging statement should always be followed by |
4a41523d | 1265 | `abort()`. |
beb0fb75 PP |
1266 | | |
1267 | * Unexpected return values from system calls. | |
4a41523d PP |
1268 | * Logic error in internal code, for example an unexpected value in a |
1269 | `switch` statement. | |
cd4aac1e PP |
1270 | * Failed assertion (within `BT_ASSERT()`). |
1271 | * Unsatisfied library precondition (within `BT_ASSERT_PRE()`). | |
1f9f5b4d | 1272 | * Unsatisfied library postcondition (within `BT_ASSERT_POST()`). |
dd22a91f | 1273 | |Almost none: always enabled. |
beb0fb75 PP |
1274 | |
1275 | |_ERROR_ | |
cd4aac1e PP |
1276 | | |
1277 | An important error which is somewhat not fatal, that is, the program, | |
beb0fb75 PP |
1278 | library, or plugin can continue to work after this, but you judge that |
1279 | it should be reported to the user. | |
1280 | ||
1281 | Usually, the program cannot recover from such an error, but it can at | |
1282 | least exit cleanly. | |
1283 | | | |
1284 | * Memory allocation errors. | |
cd4aac1e PP |
1285 | * Wrong component initialization parameters. |
1286 | * Corrupted, unrecoverable trace data. | |
beb0fb75 PP |
1287 | * Failed to perform an operation which should work considering the |
1288 | implementation and the satisfied preconditions. For example, the | |
1289 | failure to create an empty object (no parameters): most probably | |
1290 | failed internally because of an allocation error. | |
93841983 | 1291 | * Almost any error in terminal elements: CLI and plugins. |
dd22a91f | 1292 | |Almost none: always enabled. |
beb0fb75 PP |
1293 | |
1294 | |_WARN_ | |
cd4aac1e PP |
1295 | | |
1296 | An error which still allows the execution to continue, but you judge | |
1297 | that it should be reported to the user. | |
6c1b33a8 PP |
1298 | |
1299 | _WARN_-level logging statements are for any error or weird action that | |
cd4aac1e PP |
1300 | is directly or indirectly caused by the user, often through some bad |
1301 | input data. For example, not having enough memory is considered beyond | |
1302 | the user's control, so we always log memory errors with an _ERROR_ level | |
1303 | (not _FATAL_ because we usually don't abort in this condition). | |
beb0fb75 | 1304 | | |
cd4aac1e PP |
1305 | * Missing data within something that is expected to have it, but there's |
1306 | an alternative. | |
1307 | * Invalid file, but recoverable/fixable. | |
dd22a91f | 1308 | |Almost none: always enabled. |
beb0fb75 PP |
1309 | |
1310 | |_INFO_ | |
beb0fb75 | 1311 | | |
cd4aac1e PP |
1312 | Any useful information which a non-developer user would possibly |
1313 | understand. | |
1314 | ||
1315 | Anything logged with this level must _not_ happen repetitively on the | |
1316 | fast path, that is, nothing related to each message, for example. This | |
1317 | level is used for sporadic and one-shot events. | |
1318 | | | |
1319 | * CLI or component configuration report. | |
1320 | * Successful plugin, component, or message iterator initialization. | |
1321 | * In the library: anything related to plugins, graphs, component | |
1322 | classes, components, message iterators, connections, and ports which | |
1323 | is not on the fast path. | |
beb0fb75 | 1324 | * Successful connection to or disconnection from another system. |
4a41523d | 1325 | * An _optional_ subsystem cannot be loaded. |
cd4aac1e PP |
1326 | * An _optional_ field/datum cannot be found. |
1327 | | | |
dd22a91f | 1328 | Very little: always enabled. |
beb0fb75 PP |
1329 | |
1330 | |_DEBUG_ | |
beb0fb75 | 1331 | | |
cd4aac1e PP |
1332 | Something that only Babeltrace developers would be interested into, |
1333 | which can occur on the fast path, but not more often than once per | |
1334 | message. | |
1335 | ||
1336 | The _DEBUG_ level is the default <<build-time-log-level,build-time log | |
1337 | level>> as, since it's not _too_ verbose, the performance is similar to | |
1338 | an _INFO_ build. | |
1339 | | | |
1340 | * Object construction and destruction. | |
1341 | * Object recycling (except fields). | |
1342 | * Object copying (except fields and values). | |
1343 | * Object freezing (whatever the type, as freezing only occurs in | |
1344 | developer mode). | |
1345 | * Object cancellation. | |
1346 | * Calling user methods and logging the result. | |
1347 | * Setting object properties (except fields and values). | |
1348 | | | |
ef267d12 | 1349 | Noticeable, but not as much as the _TRACE_ level: could be executed |
cd4aac1e PP |
1350 | in production if you're going to need a thorough log for support |
1351 | tickets without having to rebuild the project. | |
beb0fb75 | 1352 | |
ef267d12 | 1353 | |_TRACE_ |
cd4aac1e PP |
1354 | | |
1355 | Low-level debugging context information (anything that does not fit the | |
1356 | other log levels). More appropriate for tracing in general. | |
beb0fb75 PP |
1357 | | |
1358 | * Reference count change. | |
cd4aac1e | 1359 | * Fast path, low level state machine's state change. |
beb0fb75 PP |
1360 | * Get or set an object's property. |
1361 | * Object comparison's intermediate results. | |
1362 | |Huge: not executed in production. | |
1363 | |=== | |
1364 | ||
cd4aac1e PP |
1365 | [IMPORTANT] |
1366 | -- | |
1367 | Make sure not to use a _WARN_ (or higher) log level when the | |
1368 | condition leading to the logging statement can occur under normal | |
1369 | circumstances. | |
1370 | ||
1371 | For example, a public function to get some object or | |
1372 | property from an object by name or key that fails to find the value is | |
1373 | not a warning scenario: the user could legitimately use this function to | |
1374 | check if the name/key exists in the object. In this case, use the | |
ef267d12 | 1375 | _TRACE_ level (or do not log at all). |
cd4aac1e | 1376 | -- |
b4b9064d | 1377 | |
beb0fb75 | 1378 | |
b4b9064d | 1379 | [[message]] |
cd4aac1e | 1380 | ==== Write an appropriate message |
beb0fb75 PP |
1381 | |
1382 | Follow those rules when you write a logging statement's message: | |
1383 | ||
cd4aac1e PP |
1384 | * Use an English sentence which starts with a capital letter. |
1385 | ||
1386 | * Start the sentence with the appropriate verb tense depending on the | |
1387 | context. For example: | |
beb0fb75 PP |
1388 | + |
1389 | -- | |
b4b9064d PP |
1390 | ** Beginning of operation (present continuous): _Creating ..._, |
1391 | _Copying ..._, _Serializing ..._, _Freezing ..._, _Destroying ..._ | |
1392 | ** End of operation (simple past): _Created ..._, _Successfully created ..._, | |
1393 | _Failed to create ..._, _Set ..._ (simple past of _to set_ which is | |
1394 | also _set_) | |
beb0fb75 PP |
1395 | -- |
1396 | + | |
1397 | For warning and error messages, you can start the message with _Cannot_ | |
b4b9064d | 1398 | or _Failed to_ followed by a verb if it's appropriate. |
beb0fb75 PP |
1399 | |
1400 | * Do not include the log level in the message itself. For example, | |
1401 | do not start the message with _Error while_ or _Warning:_. | |
1402 | ||
cd4aac1e PP |
1403 | * Do not put newlines, tabs, or other special characters in the message, |
1404 | unless you want to log a string with such characters. Note that | |
1405 | multiline logging messages can be hard to parse, analyze, and filter, | |
1406 | however, so prefer multiple logging statements over a single statement | |
1407 | with newlines. | |
beb0fb75 PP |
1408 | |
1409 | * **If there are fields that your logging statement must record**, | |
1410 | follow the message with `:` followed by a space, then with the list of | |
1411 | fields (more about this below). If there are no fields, end the | |
1412 | sentence with a period. | |
1413 | ||
1414 | The statement's fields _must_ be a comma-separated list of | |
cd4aac1e PP |
1415 | `__name__=__value__` tokens. Keep `__name__` as simple as possible; use |
1416 | kebab case if possible. If `__value__` is a non-alphanumeric string, put | |
1417 | it between double quotes (`"%s"` specifier). Always use the `PRId64` and | |
1418 | `PRIu64` specifiers to log an `int64_t` or an `uint64_t` value. Use `%d` | |
1419 | to log a boolean value. | |
beb0fb75 PP |
1420 | |
1421 | Example: | |
1422 | ||
cd4aac1e PP |
1423 | "Cannot read stream data for indexing: path=\"%s\", name=\"%s\", " |
1424 | "stream-id=%" PRIu64 ", stream-fd=%d, " | |
1425 | "index=%" PRIu64 ", status=%s, is-mapped=%d" | |
beb0fb75 | 1426 | |
cd4aac1e PP |
1427 | By following a standard format for the statement fields, it is easier to |
1428 | use tools like https://www.elastic.co/products/logstash[Logstash] or | |
1429 | even https://www.splunk.com/[Splunk] to split fields and analyze logs. | |
beb0fb75 PP |
1430 | |
1431 | Prefer the following suffixes in field names: | |
1432 | ||
1433 | [options="header,autowidth"] | |
1434 | |=== | |
1435 | |Field name suffix |Description |Format specifier | |
1436 | ||
1437 | |`-addr` |Memory address |`%p` | |
1438 | |`-fd` |File descriptor |`%d` | |
cd4aac1e PP |
1439 | |`-fp` |File stream (`+FILE *+`) |`%p` |
1440 | |`-id` |Object's ID |`%" PRIu64 "` | |
1441 | |`-index` |Index |`%" PRIu64 "` | |
beb0fb75 | 1442 | |`-name` |Object's name |`\"%s\"` |
beb0fb75 PP |
1443 | |=== |
1444 | ||
1445 | ||
f9ded0e0 | 1446 | === Output |
beb0fb75 PP |
1447 | |
1448 | The log is printed to the standard error stream. A log line contains the | |
cd4aac1e PP |
1449 | time, the process and thread IDs, the <<log-levels,log level>>, the |
1450 | <<choose-a-logging-tag,logging tag>>, the source's function name, file | |
1451 | name and line number, and the <<message,message>>. | |
beb0fb75 | 1452 | |
f9ded0e0 PP |
1453 | When Babeltrace supports terminal color codes (depends on the |
1454 | `BABELTRACE_TERM_COLOR` environment variable's value and what the | |
1455 | standard output and error streams are plugged into), _INFO_-level lines | |
1456 | are blue, _WARN_-level lines are yellow, and _ERROR_-level and | |
1457 | _FATAL_-level lines are red. | |
1458 | ||
1459 | Log line example: | |
beb0fb75 | 1460 | |
cd4aac1e PP |
1461 | ---- |
1462 | 05-11 00:58:03.691 23402 23402 D VALUES bt_value_destroy@values.c:498 Destroying value: addr=0xb9c3eb0 | |
1463 | ---- | |
beb0fb75 | 1464 | |
cd4aac1e PP |
1465 | You can easily filter the log with `grep` or `ag`. For example, to keep |
1466 | only the _DEBUG_-level logging messages that the `FIELD-CLASS` module | |
beb0fb75 PP |
1467 | generates: |
1468 | ||
cd4aac1e PP |
1469 | ---- |
1470 | $ babeltrace2 --log-level=D /path/to/trace |& ag 'D FIELD-CLASS' | |
1471 | ---- | |
1472 | ||
1473 | ||
1474 | == Valgrind | |
1475 | ||
1476 | To use Valgrind on an application (for example, the CLI or a test) which | |
1477 | loads libbabeltrace2, use: | |
1478 | ||
1479 | ---- | |
1480 | $ G_SLICE=always-malloc G_DEBUG=gc-friendly PYTHONMALLOC=malloc \ | |
16b7b5e7 | 1481 | LIBBABELTRACE2_NO_DLCLOSE=1 valgrind --leak-check=full \ |
cd4aac1e PP |
1482 | --suppressions=/path/to/babeltrace/extras/valgrind/popt.supp app |
1483 | ---- | |
1484 | ||
1485 | `G_SLICE=always-malloc` and `G_DEBUG=gc-friendly` is for GLib and | |
1486 | `PYTHONMALLOC=malloc` is for the Python interpreter, if it is used by | |
1487 | the Python plugin provider (Valgrind will probably show a lot of errors | |
1488 | which originate from the Python interpreter anyway). | |
1489 | ||
16b7b5e7 | 1490 | `LIBBABELTRACE2_NO_DLCLOSE=1` makes libbabeltrace2 not close the shared |
cd4aac1e PP |
1491 | libraries (plugins) which it loads. You need this to see the appropriate |
1492 | backtrace when Valgrind shows errors. | |
c637d729 FD |
1493 | |
1494 | == Testing | |
1495 | ||
1496 | === Python Bindings | |
1497 | ||
1498 | To run all the `bt2` Python package tests use: | |
1499 | ||
1500 | ---- | |
1501 | $ BT_TESTS_BUILDDIR=/path/to/build/babeltrace/tests \ | |
1502 | ./tests/bindings/python/bt2/test_python_bt2 | |
1503 | ---- | |
1504 | ||
1505 | To run all the tests in a test module (e.g. `test_event.py`) use: | |
1506 | ||
1507 | ---- | |
1508 | $ BT_TESTS_BUILDDIR=/path/to/build/babeltrace/tests \ | |
1509 | ./tests/utils/run_python_bt2 python3 ./tests/utils/python/testrunner.py \ | |
1510 | -t test_event \ | |
1511 | ./tests/bindings/python/bt2/ | |
1512 | ---- | |
1513 | ||
1514 | To run a specific test (e.g. `EventTestCase.test_clock_value`) in a test module | |
1515 | (e.g. `test_event.py`) use: | |
1516 | ||
1517 | ---- | |
1518 | $ BT_TESTS_BUILDDIR=/path/to/build/babeltrace/tests \ | |
1519 | ./tests/utils/run_python_bt2 python3 ./tests/utils/python/testrunner.py \ | |
1520 | -t test_event.EventTestCase.test_clock_value \ | |
1521 | ./tests/bindings/python/bt2/ | |
1522 | ---- |