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 | |
383 | all the Babeltrace modules. | |
beb0fb75 PP |
384 | + |
385 | The library's public API provides `bt_logging_get_minimal_level()` to | |
386 | get the configured minimal log level. | |
387 | ||
388 | [[run-time-log-level]]Run-time, dynamic log level:: | |
cd4aac1e PP |
389 | The dynamic log level is set at run time and determines the current, |
390 | _active_ log level. All the logging statements with a level below | |
391 | this level are not executed, **but they still evaluate the | |
392 | condition**. All the logging statements with a level equal to or | |
393 | greater than this level are executed, provided that their level is | |
394 | also <<build-time-log-level,enabled at build time>>. | |
beb0fb75 | 395 | + |
f9ded0e0 PP |
396 | `zf_log` has a concept of a global run-time log level which uses the |
397 | `_bt_log_global_output_lvl` symbol. In practice, we never use this | |
398 | symbol, and always make sure that `BT_LOG_OUTPUT_LEVEL` is defined to a | |
cd4aac1e PP |
399 | module-wise expression before including `"logging/log.h"`. |
400 | + | |
401 | In the library, `"lib/logging.h"` defines its own | |
402 | `BT_LOG_OUTPUT_LEVEL` to the library's log level symbol before it | |
403 | includes `"logging/log.h"` itself. | |
beb0fb75 | 404 | + |
a12f3d62 | 405 | In libbabeltrace2, the user can set the current run-time log level with |
beb0fb75 PP |
406 | the `bt_logging_set_global_level()` function, for example: |
407 | + | |
408 | -- | |
409 | [source,c] | |
410 | ---- | |
411 | bt_logging_set_global_level(BT_LOGGING_LEVEL_INFO); | |
412 | ---- | |
413 | -- | |
414 | + | |
415 | The library's initial run-time log level is defined by the | |
cd4aac1e PP |
416 | `LIBBABELTRACE2_INIT_LOG_LEVEL` environment variable, or set to _NONE_ |
417 | if this environment variable is undefined. | |
418 | + | |
419 | Other modules have their own way of setting their run-time log level. | |
420 | + | |
421 | For example, the CLI uses the `BABELTRACE_CLI_LOG_LEVEL` environment | |
422 | variable, as well as its global `--log-level` option: | |
423 | + | |
424 | ---- | |
425 | $ babeltrace2 --log-level=I ... | |
426 | ---- | |
427 | + | |
428 | The components use their own log level (as returned by | |
429 | `bt_component_get_logging_level()`). With the CLI, you can set a | |
430 | specific component's log level with its own, position-dependent | |
431 | `--log-level` option: | |
432 | + | |
433 | ---- | |
434 | $ babeltrace2 /path/to/trace -c sink.ctf.fs --log-level=D | |
435 | ---- | |
436 | + | |
437 | Code which is common to the whole project, for example `src/common` | |
438 | and `src/compat`, use function parameters to get its run-time log | |
439 | level, for example: | |
440 | + | |
441 | [source,c] | |
442 | ---- | |
443 | BT_HIDDEN | |
444 | char *bt_common_get_home_plugin_path(int log_level); | |
445 | ---- | |
beb0fb75 | 446 | + |
cd4aac1e PP |
447 | Typically, when a logging-enabled module calls such a function, it |
448 | passes its own log level expression directly (`BT_LOG_OUTPUT_LEVEL`): | |
beb0fb75 | 449 | + |
cd4aac1e PP |
450 | [source,c] |
451 | ---- | |
452 | path = bt_common_get_home_plugin_path(BT_LOG_OUTPUT_LEVEL); | |
453 | ---- | |
454 | + | |
455 | Otherwise, just pass `BT_LOG_NONE`: | |
456 | + | |
457 | ---- | |
458 | path = bt_common_get_home_plugin_path(BT_LOG_NONE); | |
459 | ---- | |
460 | ||
461 | ||
462 | [[gen-logging-statements]] | |
463 | ==== Generic logging statement macros | |
464 | ||
465 | The Babeltrace logging statement macros work just like `printf()` | |
466 | (except the `+BT_LOG*_STR()+` ones) and contain their <<log-levels,log | |
467 | level>> (short name) in their name. | |
beb0fb75 | 468 | |
cd4aac1e PP |
469 | Each of the following macros evaluate the |
470 | <<build-time-log-level,build-time log level>> definition and | |
471 | <<run-time-log-level,run-time log level>> expression (as defined by | |
472 | `BT_LOG_OUTPUT_LEVEL`) to log conditionally. | |
beb0fb75 | 473 | |
cd4aac1e PP |
474 | See <<logging-instrument-c-file-gen,Instrument a C source file |
475 | (generic)>> and <<logging-instrument-h-file-gen,Instrument a C header | |
476 | file (generic)>> to learn how to be able to use the following macros. | |
beb0fb75 | 477 | |
ef267d12 PP |
478 | `+BT_LOGT("format string", ...)+`:: |
479 | Generic trace logging statement. | |
beb0fb75 | 480 | |
cd4aac1e PP |
481 | `+BT_LOGD("format string", ...)+`:: |
482 | Generic debug logging statement. | |
beb0fb75 | 483 | |
cd4aac1e PP |
484 | `+BT_LOGI("format string", ...)+`:: |
485 | Generic info logging statement. | |
beb0fb75 | 486 | |
cd4aac1e PP |
487 | `+BT_LOGW("format string", ...)+`:: |
488 | Generic warning logging statement. | |
beb0fb75 | 489 | |
cd4aac1e PP |
490 | `+BT_LOGE("format string", ...)+`:: |
491 | Generic error logging statement. | |
beb0fb75 | 492 | |
cd4aac1e PP |
493 | `+BT_LOGF("format string", ...)+`:: |
494 | Generic fatal logging statement. | |
beb0fb75 | 495 | |
ef267d12 PP |
496 | `+BT_LOGT_STR("preformatted string")+`:: |
497 | Generic preformatted string trace logging statement. | |
beb0fb75 | 498 | |
cd4aac1e PP |
499 | `+BT_LOGD_STR("preformatted string")+`:: |
500 | Generic preformatted string debug logging statement. | |
beb0fb75 | 501 | |
cd4aac1e PP |
502 | `+BT_LOGI_STR("preformatted string")+`:: |
503 | Generic preformatted string info logging statement. | |
beb0fb75 | 504 | |
cd4aac1e PP |
505 | `+BT_LOGW_STR("preformatted string")+`:: |
506 | Generic preformatted string warning logging statement. | |
beb0fb75 | 507 | |
cd4aac1e PP |
508 | `+BT_LOGE_STR("preformatted string")+`:: |
509 | Generic preformatted string error logging statement. | |
beb0fb75 | 510 | |
cd4aac1e PP |
511 | `+BT_LOGF_STR("preformatted string")+`:: |
512 | Generic preformatted string fatal logging statement. | |
beb0fb75 | 513 | |
ef267d12 PP |
514 | `+BT_LOGT_MEM(data_ptr, data_size, "format string", ...)+`:: |
515 | Generic memory trace logging statement. | |
beb0fb75 | 516 | |
cd4aac1e PP |
517 | `+BT_LOGD_MEM(data_ptr, data_size, "format string", ...)+`:: |
518 | Generic memory debug logging statement. | |
b81626f9 | 519 | |
cd4aac1e PP |
520 | `+BT_LOGI_MEM(data_ptr, data_size, "format string", ...)+`:: |
521 | Generic memory info logging statement. | |
b81626f9 | 522 | |
cd4aac1e PP |
523 | `+BT_LOGW_MEM(data_ptr, data_size, "format string", ...)+`:: |
524 | Generic memory warning logging statement. | |
b81626f9 | 525 | |
cd4aac1e PP |
526 | `+BT_LOGE_MEM(data_ptr, data_size, "format string", ...)+`:: |
527 | Generic memory error logging statement. | |
b81626f9 | 528 | |
cd4aac1e PP |
529 | `+BT_LOGF_MEM(data_ptr, data_size, "format string", ...)+`:: |
530 | Generic memory fatal logging statement. | |
b81626f9 | 531 | |
ef267d12 PP |
532 | `+BT_LOGT_ERRNO("initial message", "format string", ...)+`:: |
533 | Generic `errno` string trace logging statement. | |
b81626f9 | 534 | |
cd4aac1e PP |
535 | `+BT_LOGD_ERRNO("initial message", "format string", ...)+`:: |
536 | Generic `errno` string debug logging statement. | |
beb0fb75 | 537 | |
cd4aac1e PP |
538 | `+BT_LOGI_ERRNO("initial message", "format string", ...)+`:: |
539 | Generic `errno` string info logging statement. | |
beb0fb75 | 540 | |
cd4aac1e PP |
541 | `+BT_LOGW_ERRNO("initial message", "format string", ...)+`:: |
542 | Generic `errno` string warning logging statement. | |
beb0fb75 | 543 | |
cd4aac1e PP |
544 | `+BT_LOGE_ERRNO("initial message", "format string", ...)+`:: |
545 | Generic `errno` string error logging statement. | |
beb0fb75 | 546 | |
cd4aac1e PP |
547 | `+BT_LOGF_ERRNO("initial message", "format string", ...)+`:: |
548 | Generic `errno` string fatal logging statement. | |
beb0fb75 | 549 | |
cd4aac1e PP |
550 | |
551 | [[lib-logging-statements]] | |
552 | ==== Library-specific logging statement macros | |
553 | ||
554 | The Babeltrace library contains an internal logging API based on the | |
555 | generic logging framework. You can use it to log known Babeltrace | |
556 | objects without having to manually log each member. | |
557 | ||
558 | See <<logging-instrument-c-file-lib,Instrument a library C source file>> | |
559 | and <<logging-instrument-h-file-lib,Instrument a library C header file>> to | |
560 | learn how to be able to use the following macros. | |
561 | ||
562 | The library logging statement macros are named `+BT_LIB_LOG*()+` instead | |
563 | of `+BT_LOG*()+`: | |
564 | ||
ef267d12 PP |
565 | `+BT_LIB_LOGT("format string", ...)+`:: |
566 | Library trace logging statement. | |
cd4aac1e PP |
567 | |
568 | `+BT_LIB_LOGD("format string", ...)+`:: | |
569 | Library debug logging statement. | |
570 | ||
571 | `+BT_LIB_LOGI("format string", ...)+`:: | |
572 | Library info logging statement. | |
573 | ||
574 | `+BT_LIB_LOGW("format string", ...)+`:: | |
575 | Library warning logging statement. | |
576 | ||
577 | `+BT_LIB_LOGE("format string", ...)+`:: | |
578 | Library error logging statement. | |
579 | ||
580 | `+BT_LIB_LOGF("format string", ...)+`:: | |
581 | Library fatal logging statement. | |
582 | ||
583 | The macros above accept the typical `printf()` conversion specifiers | |
584 | with the following limitations: | |
585 | ||
586 | * The `+*+` width specifier is not accepted. | |
587 | * The `+*+` precision specifier is not accepted. | |
588 | * The `j` and `t` length modifiers are not accepted. | |
589 | * The `n` format specifier is not accepted. | |
590 | * The format specifiers defined in `<inttypes.h>` are not accepted, | |
591 | except for `PRId64`, `PRIu64`, `PRIx64`, `PRIX64`, `PRIo64`, and | |
592 | `PRIi64`. | |
593 | ||
594 | The Babeltrace library custom conversion specifier is accepted. Its | |
595 | syntax is either `%!u` to format a UUID (`bt_uuid` type), or: | |
596 | ||
597 | . Introductory `%!` sequence. | |
598 | ||
599 | . **Optional**: `[` followed by a custom prefix for the printed fields | |
600 | of this specifier, followed by `]`. The standard form is to end this | |
601 | prefix with `-` so that, for example, with the prefix `tc-`, the | |
602 | complete field name becomes `tc-addr`. | |
603 | ||
604 | . **Optional**: `pass:[+]` to print extended object members. This | |
605 | depends on the provided format specifier. | |
606 | ||
607 | . Format specifier (see below). | |
608 | ||
609 | The available format specifiers are: | |
610 | ||
611 | [options="header,autowidth",cols="3"] | |
612 | |=== | |
613 | |Specifier | |
614 | |Object | |
615 | |Expected C type | |
616 | ||
617 | |`F` | |
618 | |Trace IR field class | |
619 | |`+struct bt_field_class *+` | |
620 | ||
621 | |`f` | |
622 | |Trace IR field | |
623 | |`+struct bt_field *+` | |
624 | ||
625 | |`P` | |
626 | |Trace IR field path | |
627 | |`+struct bt_field_path *+` | |
628 | ||
629 | |`E` | |
630 | |Trace IR event class | |
631 | |`+struct bt_event_class *+` | |
632 | ||
633 | |`e` | |
634 | |Trace IR event | |
635 | |`+struct bt_event *+` | |
636 | ||
637 | |`S` | |
638 | |Trace IR stream class. | |
639 | |`+struct bt_stream_class *+` | |
640 | ||
641 | |`s` | |
642 | |Trace IR stream | |
643 | |`+struct bt_stream *+` | |
644 | ||
645 | |`a` | |
646 | |Trace IR packet | |
647 | |`+struct bt_packet *+` | |
648 | ||
649 | |`T` | |
650 | |Trace IR trace class | |
651 | |`+struct bt_trace_class *+` | |
652 | ||
653 | |`t` | |
654 | |Trace IR trace | |
655 | |`+struct bt_trace *+` | |
656 | ||
657 | |`K` | |
658 | |Trace IR clock class | |
659 | |`+struct bt_clock_class *+` | |
660 | ||
661 | |`k` | |
662 | |Trace IR clock snapshot | |
663 | |`+struct bt_clock_snapshot *+` | |
664 | ||
665 | |`v` | |
666 | |Value object | |
667 | |`+struct bt_value *+` | |
668 | ||
669 | |`n` | |
670 | |Message | |
671 | |`+struct bt_message *+` | |
672 | ||
673 | |`i` | |
674 | |Message iterator | |
675 | |`struct bt_message_iterator *` | |
676 | ||
677 | |`C` | |
678 | |Component class | |
679 | |`struct bt_component_class *` | |
680 | ||
681 | |`c` | |
682 | |Component | |
683 | |`+struct bt_component *+` | |
684 | ||
685 | |`p` | |
686 | |Port | |
687 | |`+struct bt_port *+` | |
688 | ||
689 | |`x` | |
690 | |Connection | |
691 | |`+struct bt_connection *+` | |
692 | ||
693 | |`g` | |
694 | |Graph | |
695 | |`+struct bt_graph *+` | |
696 | ||
697 | |`l` | |
698 | |Plugin | |
699 | |`const struct bt_plugin *` | |
700 | ||
701 | |`o` | |
702 | |Object pool | |
703 | |`+struct bt_object_pool *+` | |
704 | ||
705 | |`O` | |
706 | |Object | |
707 | |`+struct bt_object *+` | |
708 | |=== | |
709 | ||
710 | Conversion specifier examples: | |
711 | ||
712 | * `%!f` | |
713 | * `%![my-event-]+e` | |
714 | * `%!t` | |
715 | * `%!+F` | |
716 | ||
717 | The ``, `` string (comma and space) is printed between individual | |
718 | fields, but **not after the last one**. Therefore, you must put this | |
719 | separator in the format string between two conversion specifiers, for | |
720 | example: | |
721 | ||
722 | [source,c] | |
723 | ---- | |
724 | BT_LIB_LOGW("Message: count=%u, %!E, %!+K", count, event_class, clock_class); | |
725 | ---- | |
726 | ||
727 | Example with a custom prefix: | |
728 | ||
729 | [source,c] | |
730 | ---- | |
731 | BT_LIB_LOGI("Some message: %![ec-a-]e, %![ec-b-]+e", ec_a, ec_b); | |
732 | ---- | |
733 | ||
734 | It is safe to pass `NULL` as any Babeltrace object parameter: the macros | |
735 | only print its null address. | |
736 | ||
737 | WARNING: Build-time `printf()` format checks are disabled for the | |
738 | `+BT_LIB_LOG*()+` macros because there are custom conversion specifiers, | |
739 | so make sure to test your logging statements. | |
740 | ||
741 | ||
742 | [[comp-logging-statements]] | |
743 | ==== Component-specific logging statement macros | |
744 | ||
745 | There are available logging macros for components. They prepend a prefix | |
746 | including the component's name to the logging message. | |
747 | ||
748 | See <<logging-instrument-c-file-compcls,Instrument a component class C | |
749 | source file>> and <<logging-instrument-h-file-compcls,Instrument a | |
750 | component class C header file>> to learn how to be able to use the | |
751 | following macros. | |
752 | ||
753 | The component logging statement macros are named `+BT_COMP_LOG*()+` | |
754 | instead of `+BT_LOG*()+`: | |
755 | ||
ef267d12 PP |
756 | `+BT_COMP_LOGT("format string", ...)+`:: |
757 | Component trace logging statement. | |
cd4aac1e PP |
758 | |
759 | `+BT_COMP_LOGD("format string", ...)+`:: | |
760 | Component debug logging statement. | |
761 | ||
762 | `+BT_COMP_LOGI("format string", ...)+`:: | |
763 | Component info logging statement. | |
764 | ||
765 | `+BT_COMP_LOGW("format string", ...)+`:: | |
766 | Component warning logging statement. | |
767 | ||
768 | `+BT_COMP_LOGE("format string", ...)+`:: | |
769 | Component error logging statement. | |
770 | ||
771 | `+BT_COMP_LOGF("format string", ...)+`:: | |
772 | Component fatal logging statement. | |
773 | ||
ef267d12 PP |
774 | `+BT_COMP_LOGT_STR("preformatted string")+`:: |
775 | Component preformatted string trace logging statement. | |
cd4aac1e PP |
776 | |
777 | `+BT_COMP_LOGD_STR("preformatted string")+`:: | |
778 | Component preformatted string debug logging statement. | |
779 | ||
780 | `+BT_COMP_LOGI_STR("preformatted string")+`:: | |
781 | Component preformatted string info logging statement. | |
782 | ||
783 | `+BT_COMP_LOGW_STR("preformatted string")+`:: | |
784 | Component preformatted string warning logging statement. | |
785 | ||
786 | `+BT_COMP_LOGE_STR("preformatted string")+`:: | |
787 | Component preformatted string error logging statement. | |
788 | ||
789 | `+BT_COMP_LOGF_STR("preformatted string")+`:: | |
790 | Component preformatted string fatal logging statement. | |
791 | ||
ef267d12 PP |
792 | `+BT_COMP_LOGT_ERRNO("initial message", "format string", ...)+`:: |
793 | Component `errno` string trace logging statement. | |
cd4aac1e PP |
794 | |
795 | `+BT_COMP_LOGD_ERRNO("initial message", "format string", ...)+`:: | |
796 | Component `errno` string debug logging statement. | |
797 | ||
798 | `+BT_COMP_LOGI_ERRNO("initial message", "format string", ...)+`:: | |
799 | Component `errno` string info logging statement. | |
800 | ||
801 | `+BT_COMP_LOGW_ERRNO("initial message", "format string", ...)+`:: | |
802 | Component `errno` string warning logging statement. | |
803 | ||
804 | `+BT_COMP_LOGE_ERRNO("initial message", "format string", ...)+`:: | |
805 | Component `errno` string error logging statement. | |
806 | ||
807 | `+BT_COMP_LOGF_ERRNO("initial message", "format string", ...)+`:: | |
808 | Component `errno` string fatal logging statement. | |
809 | ||
ef267d12 PP |
810 | `+BT_COMP_LOGT_MEM(data_ptr, data_size, "format string", ...)+`:: |
811 | Component memory trace logging statement. | |
cd4aac1e PP |
812 | |
813 | `+BT_COMP_LOGD_MEM(data_ptr, data_size, "format string", ...)+`:: | |
814 | Component memory debug logging statement. | |
815 | ||
816 | `+BT_COMP_LOGI_MEM(data_ptr, data_size, "format string", ...)+`:: | |
817 | Component memory info logging statement. | |
818 | ||
819 | `+BT_COMP_LOGW_MEM(data_ptr, data_size, "format string", ...)+`:: | |
820 | Component memory warning logging statement. | |
821 | ||
822 | `+BT_COMP_LOGE_MEM(data_ptr, data_size, "format string", ...)+`:: | |
823 | Component memory error logging statement. | |
824 | ||
825 | `+BT_COMP_LOGF_MEM(data_ptr, data_size, "format string", ...)+`:: | |
826 | Component memory fatal logging statement. | |
beb0fb75 PP |
827 | |
828 | ||
f9ded0e0 | 829 | ==== Conditional logging |
beb0fb75 | 830 | |
cd4aac1e | 831 | `+BT_LOG_IF(cond, statement)+`:: |
beb0fb75 PP |
832 | Execute `statement` only if `cond` is true. |
833 | + | |
834 | Example: | |
835 | + | |
836 | -- | |
837 | [source,c] | |
838 | ---- | |
839 | BT_LOG_IF(i < count / 2, BT_LOGD("Log this: i=%d", i)); | |
840 | ---- | |
841 | -- | |
842 | ||
843 | To check the <<build-time-log-level,build-time log level>>: | |
844 | ||
845 | [source,c] | |
846 | ---- | |
847 | #if BT_LOG_ENABLED_DEBUG | |
848 | ... | |
849 | #endif | |
850 | ---- | |
851 | ||
cd4aac1e PP |
852 | This tests if the _DEBUG_ level was enabled at build time. This means |
853 | that the current, <<run-time-log-level,run-time log level>> _could_ be | |
f9ded0e0 PP |
854 | _DEBUG_, but it could also be higher. The rule of thumb is to use only |
855 | logging statements at the same level in a `BT_LOG_ENABLED_*` conditional | |
856 | block. | |
beb0fb75 PP |
857 | |
858 | The available definitions for build-time conditions are: | |
859 | ||
ef267d12 | 860 | * `BT_LOG_ENABLED_TRACE` |
beb0fb75 PP |
861 | * `BT_LOG_ENABLED_DEBUG` |
862 | * `BT_LOG_ENABLED_INFO` | |
863 | * `BT_LOG_ENABLED_WARN` | |
864 | * `BT_LOG_ENABLED_ERROR` | |
865 | * `BT_LOG_ENABLED_FATAL` | |
866 | ||
867 | To check the current, <<run-time-log-level,run-time log level>>: | |
868 | ||
869 | [source,c] | |
870 | ---- | |
871 | if (BT_LOG_ON_DEBUG) { | |
872 | ... | |
873 | } | |
874 | ---- | |
875 | ||
876 | This tests if the _DEBUG_ log level is dynamically turned on | |
cd4aac1e | 877 | (implies that it's also enabled at build time). This check could have a |
beb0fb75 PP |
878 | noticeable impact on performance. |
879 | ||
880 | The available definitions for run-time conditions are: | |
881 | ||
ef267d12 | 882 | * `BT_LOG_ON_TRACE` |
beb0fb75 PP |
883 | * `BT_LOG_ON_DEBUG` |
884 | * `BT_LOG_ON_INFO` | |
885 | * `BT_LOG_ON_WARN` | |
886 | * `BT_LOG_ON_ERROR` | |
887 | * `BT_LOG_ON_FATAL` | |
888 | ||
cd4aac1e PP |
889 | Those macros check the module-specific log level symbol (defined by |
890 | `BT_LOG_OUTPUT_LEVEL`). | |
beb0fb75 PP |
891 | |
892 | Never, ever write code which would be executed only to compute the | |
893 | fields of a logging statement outside a conditional logging scope, | |
894 | for example: | |
895 | ||
896 | [source,c] | |
897 | ---- | |
898 | int number = get_number_of_event_classes_with_property_x(...); | |
899 | BT_LOGD("Bla bla: number=%d", number); | |
900 | ---- | |
901 | ||
902 | Do this instead: | |
903 | ||
904 | [source,c] | |
905 | ---- | |
906 | if (BT_LOG_ON_DEBUG) { | |
907 | int number = get_number_of_event_classes_with_property_x(...); | |
908 | BT_LOGD("Bla bla: number=%d", number); | |
909 | } | |
910 | ---- | |
911 | ||
912 | Or even this: | |
913 | ||
914 | [source,c] | |
915 | ---- | |
916 | BT_LOGD("Bla bla: number=%d", get_number_of_event_classes_with_property_x(...)); | |
917 | ---- | |
918 | ||
919 | ||
cd4aac1e | 920 | === Guides |
beb0fb75 | 921 | |
cd4aac1e PP |
922 | [[logging-instrument-c-file-gen]] |
923 | ==== Instrument a C source file (generic) | |
beb0fb75 | 924 | |
cd4aac1e PP |
925 | To instrument a C source file (`.c`): |
926 | ||
927 | . At the top of the file, before the first `#include` line (if any), | |
928 | define your file's <<choose-a-logging-tag,logging tag>> name: | |
4a41523d PP |
929 | + |
930 | -- | |
931 | [source,c] | |
932 | ---- | |
cd4aac1e | 933 | #define BT_LOG_TAG "SUBSYS/MY-MODULE/MY-FILE" |
4a41523d PP |
934 | ---- |
935 | -- | |
cd4aac1e PP |
936 | |
937 | . Below the line above, define the source file's log level expression, | |
938 | `BT_LOG_OUTPUT_LEVEL`. This expression is evaluated for each | |
939 | <<gen-logging-statements,logging statement>> to know the current | |
940 | <<run-time-log-level,run-time log level>>. | |
941 | + | |
942 | Examples: | |
943 | + | |
944 | [source,c] | |
945 | ---- | |
946 | /* Global log level variable */ | |
947 | #define BT_LOG_OUTPUT_LEVEL module_global_log_level | |
948 | ---- | |
4a41523d | 949 | + |
cd4aac1e PP |
950 | [source,c] |
951 | ---- | |
952 | /* Local log level variable; must exist where you use BT_LOG*() */ | |
953 | #define BT_LOG_OUTPUT_LEVEL log_level | |
954 | ---- | |
955 | + | |
956 | [source,c] | |
957 | ---- | |
958 | /* Object's log level; `obj` must exist where you use BT_LOG*() */ | |
959 | #define BT_LOG_OUTPUT_LEVEL (obj->log_level) | |
960 | ---- | |
4a41523d | 961 | |
cd4aac1e | 962 | . Include `"logging/log.h"`: |
4a41523d | 963 | + |
beb0fb75 PP |
964 | [source,c] |
965 | ---- | |
578e048b | 966 | #include "logging/log.h" |
cd4aac1e | 967 | ---- |
4a41523d | 968 | |
cd4aac1e PP |
969 | . In the file, instrument your code with the |
970 | <<gen-logging-statements,generic logging statement macros>>. | |
4a41523d | 971 | |
cd4aac1e PP |
972 | |
973 | [[logging-instrument-h-file-gen]] | |
974 | ==== Instrument a C header file (generic) | |
975 | ||
976 | To instrument a C header file (`.h`), if you have `static inline` | |
977 | functions in it: | |
978 | ||
979 | . Do not include `"logging/log.h"`! | |
980 | ||
981 | . Do one of: | |
982 | ||
983 | .. In the file, instrument your code with the | |
984 | <<gen-logging-statements,generic logging statement macros>>, making | |
985 | each of them conditional to the existence of the macro you're using: | |
4a41523d | 986 | + |
cd4aac1e PP |
987 | [source,c] |
988 | ---- | |
989 | static inline | |
990 | int some_function(int x) | |
991 | { | |
992 | /* ... */ | |
4a41523d | 993 | |
ef267d12 PP |
994 | #ifdef BT_LOGT |
995 | BT_LOGT(...); | |
cd4aac1e | 996 | #endif |
beb0fb75 | 997 | |
cd4aac1e | 998 | /* ... */ |
6470c171 | 999 | |
cd4aac1e PP |
1000 | #ifdef BT_LOGW_STR |
1001 | BT_LOGW_STR(...); | |
1002 | #endif | |
f9ded0e0 | 1003 | |
cd4aac1e PP |
1004 | /* ... */ |
1005 | } | |
1006 | ---- | |
1007 | + | |
1008 | The C source files which include this header file determine if logging | |
1009 | is enabled or not for them, and if so, what is their | |
1010 | <<choose-a-logging-tag,logging tag>> and <<run-time-log-level,run-time | |
1011 | log level>> expression. | |
f9ded0e0 | 1012 | |
cd4aac1e PP |
1013 | .. Require that logging be enabled: |
1014 | + | |
1015 | [source,c] | |
1016 | ---- | |
1017 | /* Protection: this file uses BT_LOG*() macros directly */ | |
1018 | #ifndef BT_LOG_SUPPORTED | |
1019 | # error Please include "logging/log.h" before including this file. | |
1020 | #endif | |
1021 | ---- | |
1022 | + | |
1023 | Then, in the file, instrument your code with the | |
1024 | <<gen-logging-statements,generic logging statement macros>>. | |
1025 | ||
1026 | ||
1027 | [[logging-instrument-c-file-lib]] | |
1028 | ==== Instrument a library C source file | |
1029 | ||
1030 | To instrument a library C source file (`.c`): | |
4a41523d PP |
1031 | |
1032 | . At the top of the file, before the first `#include` line (if any), | |
cd4aac1e PP |
1033 | define your file's <<choose-a-logging-tag,logging tag>> name (this |
1034 | tag must start with `LIB/`): | |
4a41523d PP |
1035 | + |
1036 | -- | |
1037 | [source,c] | |
1038 | ---- | |
cd4aac1e | 1039 | #define BT_LOG_TAG "LIB/THE-FILE" |
4a41523d PP |
1040 | ---- |
1041 | -- | |
cd4aac1e PP |
1042 | |
1043 | . Include `"lib/logging.h"`: | |
4a41523d | 1044 | + |
cd4aac1e PP |
1045 | [source,c] |
1046 | ---- | |
1047 | #include "lib/logging.h" | |
1048 | ---- | |
4a41523d | 1049 | |
cd4aac1e PP |
1050 | . In the file, instrument your code with the |
1051 | <<lib-logging-statements,library logging statement macros>> or with | |
1052 | the <<gen-logging-statements,generic logging statement macros>>. | |
4a41523d | 1053 | |
f9ded0e0 | 1054 | |
cd4aac1e PP |
1055 | [[logging-instrument-h-file-lib]] |
1056 | ==== Instrument a library C header file | |
1057 | ||
1058 | To instrument a library C header file (`.h`), if you have `static | |
1059 | inline` functions in it: | |
1060 | ||
1061 | . Do not include `"lib/logging.h"`! | |
1062 | ||
1063 | . Require that library logging be enabled: | |
1064 | + | |
1065 | [source,c] | |
1066 | ---- | |
1067 | /* Protection: this file uses BT_LIB_LOG*() macros directly */ | |
1068 | #ifndef BT_LIB_LOG_SUPPORTED | |
1069 | # error Please include "lib/logging.h" before including this file. | |
1070 | #endif | |
1071 | ---- | |
1072 | ||
1073 | . In the file, instrument your code with the | |
1074 | <<lib-logging-statements,library logging statement macros>> or with | |
1075 | the <<gen-logging-statements,generic logging statement macros>>. | |
f9ded0e0 | 1076 | |
4a41523d | 1077 | |
cd4aac1e PP |
1078 | [[logging-instrument-c-file-compcls]] |
1079 | ==== Instrument a component class C source file | |
1080 | ||
1081 | To instrument a component class C source file (`.c`): | |
1082 | ||
1083 | . At the top of the file, before the first `#include` line (if any), | |
1084 | define your file's <<choose-a-logging-tag,logging tag>> name (this tag | |
1085 | must start with `PLUGIN/` followed by the component class identifier): | |
4a41523d PP |
1086 | + |
1087 | -- | |
1088 | [source,c] | |
1089 | ---- | |
cd4aac1e PP |
1090 | #define BT_LOG_TAG "PLUGIN/SRC.MY-PLUGIN.MY-SRC" |
1091 | ---- | |
1092 | -- | |
4a41523d | 1093 | |
cd4aac1e PP |
1094 | . Below the line above, define the source file's log level expression, |
1095 | `BT_LOG_OUTPUT_LEVEL`. This expression is evaluated for each | |
1096 | <<comp-logging-statements,logging statement>> to know the current | |
1097 | <<run-time-log-level,run-time log level>>. | |
1098 | + | |
1099 | For a component class file, it is usually a member of a local component | |
1100 | private structure variable: | |
1101 | + | |
1102 | [source,c] | |
1103 | ---- | |
1104 | #define BT_LOG_OUTPUT_LEVEL (my_comp->log_level) | |
1105 | ---- | |
4a41523d | 1106 | |
cd4aac1e PP |
1107 | . Below the line above, define `BT_COMP_LOG_SELF_COMP` to an expression |
1108 | which, evaluated in the context of the | |
1109 | <<comp-logging-statements,logging statements>>, evaluates to the self | |
1110 | component address (`+bt_self_component *+`) of the component. | |
1111 | + | |
1112 | This is usually a member of a local component private structure | |
1113 | variable: | |
1114 | + | |
1115 | [source,c] | |
1116 | ---- | |
1117 | #define BT_COMP_LOG_SELF_COMP (my_comp->self_comp) | |
1118 | ---- | |
1119 | ||
1120 | . Include `"plugins/comp-logging.h"`: | |
1121 | + | |
1122 | [source,c] | |
1123 | ---- | |
1124 | #include "plugins/comp-logging.h" | |
1125 | ---- | |
1126 | ||
1127 | . In the component initialization method, make sure to set the | |
1128 | component private structure's log level member to the initial | |
1129 | component's log level: | |
1130 | + | |
1131 | [source,c] | |
1132 | ---- | |
1133 | struct my_comp { | |
1134 | bt_logging_level log_level; | |
4a41523d | 1135 | /* ... */ |
cd4aac1e | 1136 | }; |
4a41523d | 1137 | |
cd4aac1e PP |
1138 | BT_HIDDEN |
1139 | bt_self_component_status my_comp_init( | |
1140 | bt_self_component_source *self_comp_src, | |
1141 | bt_value *params, void *init_method_data) | |
1142 | { | |
1143 | struct my_comp *my_comp = g_new0(struct my_comp, 1); | |
1144 | bt_self_component *self_comp = | |
1145 | bt_self_component_source_as_self_component(self_comp_src); | |
1146 | const bt_component *comp = bt_self_component_as_component(self_comp); | |
1147 | ||
1148 | BT_ASSERT(my_comp); | |
1149 | my_comp->log_level = bt_component_get_logging_level(comp); | |
4a41523d PP |
1150 | |
1151 | /* ... */ | |
1152 | } | |
1153 | ---- | |
cd4aac1e PP |
1154 | |
1155 | . In the file, instrument your code with the | |
1156 | <<comp-logging-statements,component logging statement macros>>. | |
1157 | ||
1158 | ||
1159 | [[logging-instrument-h-file-compcls]] | |
1160 | ==== Instrument a component class C header file | |
1161 | ||
1162 | To instrument a component class C header file (`.h`), if you have | |
1163 | `static inline` functions in it: | |
1164 | ||
1165 | . Do not include `"plugins/comp-logging.h"`! | |
1166 | ||
1167 | . Require that component logging be enabled: | |
4a41523d | 1168 | + |
cd4aac1e PP |
1169 | [source,c] |
1170 | ---- | |
1171 | /* Protection: this file uses BT_COMP_LOG*() macros directly */ | |
1172 | #ifndef BT_COMP_LOG_SUPPORTED | |
1173 | # error Please include "plugins/comp-logging.h" before including this file. | |
1174 | #endif | |
1175 | ---- | |
1176 | ||
1177 | . In the file, instrument your code with the | |
1178 | <<comp-logging-statements,component logging statement macros>>. | |
1179 | ||
1180 | ||
1181 | [[choose-a-logging-tag]] | |
1182 | ==== Choose a logging tag | |
beb0fb75 | 1183 | |
cd4aac1e PP |
1184 | Each logging-enabled C source file must define `BT_LOG_TAG` to a logging |
1185 | tag. A logging tag is a namespace to identify the logging messages of | |
1186 | this specific source file. | |
beb0fb75 | 1187 | |
cd4aac1e PP |
1188 | In general, a logging tag name _must_ be only uppercase letters, digits, |
1189 | and the `-`, `.`, and `/` characters. | |
beb0fb75 | 1190 | |
cd4aac1e PP |
1191 | Use `/` to show the subsystem to source file hierarchy. |
1192 | ||
1193 | For the Babeltrace library, start with `LIB/`. | |
1194 | ||
1195 | For the CTF writer library, start with `CTF-WRITER/`. | |
1196 | ||
1197 | For component classes, use: | |
beb0fb75 | 1198 | |
93841983 | 1199 | [verse] |
cd4aac1e PP |
1200 | `PLUGIN/__CCTYPE__.__PNAME__.__CCNAME__[/__FILE__]` |
1201 | ||
1202 | With: | |
1203 | ||
1204 | `__CCTYPE__`:: | |
1205 | Component class's type (`SRC`, `FLT`, or `SINK`). | |
beb0fb75 | 1206 | |
cd4aac1e | 1207 | `__PNAME__`:: |
93841983 | 1208 | Plugin's name. |
beb0fb75 | 1209 | |
cd4aac1e | 1210 | `__CCNAME__`:: |
93841983 | 1211 | Component class's name. |
beb0fb75 | 1212 | |
cd4aac1e | 1213 | `__FILE__`:: |
93841983 | 1214 | Additional information to specify the source file name or module. |
beb0fb75 | 1215 | |
cd4aac1e | 1216 | For plugins (files common to many component classes), use: |
beb0fb75 | 1217 | |
cd4aac1e PP |
1218 | [verse] |
1219 | `PLUGIN/__PNAME__[/__FILE__]` | |
beb0fb75 | 1220 | |
cd4aac1e | 1221 | With: |
beb0fb75 | 1222 | |
cd4aac1e PP |
1223 | `__PNAME__`:: |
1224 | Plugin's name. | |
1225 | ||
1226 | `__FILE__`:: | |
1227 | Additional information to specify the source file name or module. | |
1228 | ||
1229 | ||
1230 | [[choose-a-log-level]] | |
1231 | ==== Choose a log level | |
beb0fb75 PP |
1232 | |
1233 | Choosing the appropriate level for your logging statement is very | |
1234 | important. | |
1235 | ||
cd4aac1e | 1236 | [options="header,autowidth",cols="1,2,3a,4"] |
beb0fb75 | 1237 | |=== |
cd4aac1e | 1238 | |Log level |Description |Use cases |Expected impact on performance |
beb0fb75 PP |
1239 | |
1240 | |_FATAL_ | |
cd4aac1e PP |
1241 | | |
1242 | The program, library, or plugin cannot continue to work in this | |
beb0fb75 PP |
1243 | condition: it must be terminated immediately. |
1244 | ||
b4b9064d | 1245 | A _FATAL_-level logging statement should always be followed by |
4a41523d | 1246 | `abort()`. |
beb0fb75 PP |
1247 | | |
1248 | * Unexpected return values from system calls. | |
4a41523d PP |
1249 | * Logic error in internal code, for example an unexpected value in a |
1250 | `switch` statement. | |
cd4aac1e PP |
1251 | * Failed assertion (within `BT_ASSERT()`). |
1252 | * Unsatisfied library precondition (within `BT_ASSERT_PRE()`). | |
beb0fb75 PP |
1253 | |Almost none: should be executed in production. |
1254 | ||
1255 | |_ERROR_ | |
cd4aac1e PP |
1256 | | |
1257 | An important error which is somewhat not fatal, that is, the program, | |
beb0fb75 PP |
1258 | library, or plugin can continue to work after this, but you judge that |
1259 | it should be reported to the user. | |
1260 | ||
1261 | Usually, the program cannot recover from such an error, but it can at | |
1262 | least exit cleanly. | |
1263 | | | |
1264 | * Memory allocation errors. | |
cd4aac1e PP |
1265 | * Wrong component initialization parameters. |
1266 | * Corrupted, unrecoverable trace data. | |
beb0fb75 PP |
1267 | * Failed to perform an operation which should work considering the |
1268 | implementation and the satisfied preconditions. For example, the | |
1269 | failure to create an empty object (no parameters): most probably | |
1270 | failed internally because of an allocation error. | |
93841983 | 1271 | * Almost any error in terminal elements: CLI and plugins. |
beb0fb75 PP |
1272 | |Almost none: should be executed in production. |
1273 | ||
1274 | |_WARN_ | |
cd4aac1e PP |
1275 | | |
1276 | An error which still allows the execution to continue, but you judge | |
1277 | that it should be reported to the user. | |
6c1b33a8 PP |
1278 | |
1279 | _WARN_-level logging statements are for any error or weird action that | |
cd4aac1e PP |
1280 | is directly or indirectly caused by the user, often through some bad |
1281 | input data. For example, not having enough memory is considered beyond | |
1282 | the user's control, so we always log memory errors with an _ERROR_ level | |
1283 | (not _FATAL_ because we usually don't abort in this condition). | |
beb0fb75 | 1284 | | |
cd4aac1e PP |
1285 | * Missing data within something that is expected to have it, but there's |
1286 | an alternative. | |
1287 | * Invalid file, but recoverable/fixable. | |
beb0fb75 PP |
1288 | |Almost none: can be executed in production. |
1289 | ||
1290 | |_INFO_ | |
beb0fb75 | 1291 | | |
cd4aac1e PP |
1292 | Any useful information which a non-developer user would possibly |
1293 | understand. | |
1294 | ||
1295 | Anything logged with this level must _not_ happen repetitively on the | |
1296 | fast path, that is, nothing related to each message, for example. This | |
1297 | level is used for sporadic and one-shot events. | |
1298 | | | |
1299 | * CLI or component configuration report. | |
1300 | * Successful plugin, component, or message iterator initialization. | |
1301 | * In the library: anything related to plugins, graphs, component | |
1302 | classes, components, message iterators, connections, and ports which | |
1303 | is not on the fast path. | |
beb0fb75 | 1304 | * Successful connection to or disconnection from another system. |
4a41523d | 1305 | * An _optional_ subsystem cannot be loaded. |
cd4aac1e PP |
1306 | * An _optional_ field/datum cannot be found. |
1307 | | | |
1308 | Very little: can be executed in production if _INFO_ level information | |
1309 | is desired. | |
beb0fb75 PP |
1310 | |
1311 | |_DEBUG_ | |
beb0fb75 | 1312 | | |
cd4aac1e PP |
1313 | Something that only Babeltrace developers would be interested into, |
1314 | which can occur on the fast path, but not more often than once per | |
1315 | message. | |
1316 | ||
1317 | The _DEBUG_ level is the default <<build-time-log-level,build-time log | |
1318 | level>> as, since it's not _too_ verbose, the performance is similar to | |
1319 | an _INFO_ build. | |
1320 | | | |
1321 | * Object construction and destruction. | |
1322 | * Object recycling (except fields). | |
1323 | * Object copying (except fields and values). | |
1324 | * Object freezing (whatever the type, as freezing only occurs in | |
1325 | developer mode). | |
1326 | * Object cancellation. | |
1327 | * Calling user methods and logging the result. | |
1328 | * Setting object properties (except fields and values). | |
1329 | | | |
ef267d12 | 1330 | Noticeable, but not as much as the _TRACE_ level: could be executed |
cd4aac1e PP |
1331 | in production if you're going to need a thorough log for support |
1332 | tickets without having to rebuild the project. | |
beb0fb75 | 1333 | |
ef267d12 | 1334 | |_TRACE_ |
cd4aac1e PP |
1335 | | |
1336 | Low-level debugging context information (anything that does not fit the | |
1337 | other log levels). More appropriate for tracing in general. | |
beb0fb75 PP |
1338 | | |
1339 | * Reference count change. | |
cd4aac1e | 1340 | * Fast path, low level state machine's state change. |
beb0fb75 PP |
1341 | * Get or set an object's property. |
1342 | * Object comparison's intermediate results. | |
1343 | |Huge: not executed in production. | |
1344 | |=== | |
1345 | ||
cd4aac1e PP |
1346 | [IMPORTANT] |
1347 | -- | |
1348 | Make sure not to use a _WARN_ (or higher) log level when the | |
1349 | condition leading to the logging statement can occur under normal | |
1350 | circumstances. | |
1351 | ||
1352 | For example, a public function to get some object or | |
1353 | property from an object by name or key that fails to find the value is | |
1354 | not a warning scenario: the user could legitimately use this function to | |
1355 | check if the name/key exists in the object. In this case, use the | |
ef267d12 | 1356 | _TRACE_ level (or do not log at all). |
cd4aac1e | 1357 | -- |
b4b9064d | 1358 | |
beb0fb75 | 1359 | |
b4b9064d | 1360 | [[message]] |
cd4aac1e | 1361 | ==== Write an appropriate message |
beb0fb75 PP |
1362 | |
1363 | Follow those rules when you write a logging statement's message: | |
1364 | ||
cd4aac1e PP |
1365 | * Use an English sentence which starts with a capital letter. |
1366 | ||
1367 | * Start the sentence with the appropriate verb tense depending on the | |
1368 | context. For example: | |
beb0fb75 PP |
1369 | + |
1370 | -- | |
b4b9064d PP |
1371 | ** Beginning of operation (present continuous): _Creating ..._, |
1372 | _Copying ..._, _Serializing ..._, _Freezing ..._, _Destroying ..._ | |
1373 | ** End of operation (simple past): _Created ..._, _Successfully created ..._, | |
1374 | _Failed to create ..._, _Set ..._ (simple past of _to set_ which is | |
1375 | also _set_) | |
beb0fb75 PP |
1376 | -- |
1377 | + | |
1378 | For warning and error messages, you can start the message with _Cannot_ | |
b4b9064d | 1379 | or _Failed to_ followed by a verb if it's appropriate. |
beb0fb75 PP |
1380 | |
1381 | * Do not include the log level in the message itself. For example, | |
1382 | do not start the message with _Error while_ or _Warning:_. | |
1383 | ||
cd4aac1e PP |
1384 | * Do not put newlines, tabs, or other special characters in the message, |
1385 | unless you want to log a string with such characters. Note that | |
1386 | multiline logging messages can be hard to parse, analyze, and filter, | |
1387 | however, so prefer multiple logging statements over a single statement | |
1388 | with newlines. | |
beb0fb75 PP |
1389 | |
1390 | * **If there are fields that your logging statement must record**, | |
1391 | follow the message with `:` followed by a space, then with the list of | |
1392 | fields (more about this below). If there are no fields, end the | |
1393 | sentence with a period. | |
1394 | ||
1395 | The statement's fields _must_ be a comma-separated list of | |
cd4aac1e PP |
1396 | `__name__=__value__` tokens. Keep `__name__` as simple as possible; use |
1397 | kebab case if possible. If `__value__` is a non-alphanumeric string, put | |
1398 | it between double quotes (`"%s"` specifier). Always use the `PRId64` and | |
1399 | `PRIu64` specifiers to log an `int64_t` or an `uint64_t` value. Use `%d` | |
1400 | to log a boolean value. | |
beb0fb75 PP |
1401 | |
1402 | Example: | |
1403 | ||
cd4aac1e PP |
1404 | "Cannot read stream data for indexing: path=\"%s\", name=\"%s\", " |
1405 | "stream-id=%" PRIu64 ", stream-fd=%d, " | |
1406 | "index=%" PRIu64 ", status=%s, is-mapped=%d" | |
beb0fb75 | 1407 | |
cd4aac1e PP |
1408 | By following a standard format for the statement fields, it is easier to |
1409 | use tools like https://www.elastic.co/products/logstash[Logstash] or | |
1410 | even https://www.splunk.com/[Splunk] to split fields and analyze logs. | |
beb0fb75 PP |
1411 | |
1412 | Prefer the following suffixes in field names: | |
1413 | ||
1414 | [options="header,autowidth"] | |
1415 | |=== | |
1416 | |Field name suffix |Description |Format specifier | |
1417 | ||
1418 | |`-addr` |Memory address |`%p` | |
1419 | |`-fd` |File descriptor |`%d` | |
cd4aac1e PP |
1420 | |`-fp` |File stream (`+FILE *+`) |`%p` |
1421 | |`-id` |Object's ID |`%" PRIu64 "` | |
1422 | |`-index` |Index |`%" PRIu64 "` | |
beb0fb75 | 1423 | |`-name` |Object's name |`\"%s\"` |
beb0fb75 PP |
1424 | |=== |
1425 | ||
1426 | ||
f9ded0e0 | 1427 | === Output |
beb0fb75 PP |
1428 | |
1429 | The log is printed to the standard error stream. A log line contains the | |
cd4aac1e PP |
1430 | time, the process and thread IDs, the <<log-levels,log level>>, the |
1431 | <<choose-a-logging-tag,logging tag>>, the source's function name, file | |
1432 | name and line number, and the <<message,message>>. | |
beb0fb75 | 1433 | |
f9ded0e0 PP |
1434 | When Babeltrace supports terminal color codes (depends on the |
1435 | `BABELTRACE_TERM_COLOR` environment variable's value and what the | |
1436 | standard output and error streams are plugged into), _INFO_-level lines | |
1437 | are blue, _WARN_-level lines are yellow, and _ERROR_-level and | |
1438 | _FATAL_-level lines are red. | |
1439 | ||
1440 | Log line example: | |
beb0fb75 | 1441 | |
cd4aac1e PP |
1442 | ---- |
1443 | 05-11 00:58:03.691 23402 23402 D VALUES bt_value_destroy@values.c:498 Destroying value: addr=0xb9c3eb0 | |
1444 | ---- | |
beb0fb75 | 1445 | |
cd4aac1e PP |
1446 | You can easily filter the log with `grep` or `ag`. For example, to keep |
1447 | only the _DEBUG_-level logging messages that the `FIELD-CLASS` module | |
beb0fb75 PP |
1448 | generates: |
1449 | ||
cd4aac1e PP |
1450 | ---- |
1451 | $ babeltrace2 --log-level=D /path/to/trace |& ag 'D FIELD-CLASS' | |
1452 | ---- | |
1453 | ||
1454 | ||
1455 | == Valgrind | |
1456 | ||
1457 | To use Valgrind on an application (for example, the CLI or a test) which | |
1458 | loads libbabeltrace2, use: | |
1459 | ||
1460 | ---- | |
1461 | $ G_SLICE=always-malloc G_DEBUG=gc-friendly PYTHONMALLOC=malloc \ | |
16b7b5e7 | 1462 | LIBBABELTRACE2_NO_DLCLOSE=1 valgrind --leak-check=full \ |
cd4aac1e PP |
1463 | --suppressions=/path/to/babeltrace/extras/valgrind/popt.supp app |
1464 | ---- | |
1465 | ||
1466 | `G_SLICE=always-malloc` and `G_DEBUG=gc-friendly` is for GLib and | |
1467 | `PYTHONMALLOC=malloc` is for the Python interpreter, if it is used by | |
1468 | the Python plugin provider (Valgrind will probably show a lot of errors | |
1469 | which originate from the Python interpreter anyway). | |
1470 | ||
16b7b5e7 | 1471 | `LIBBABELTRACE2_NO_DLCLOSE=1` makes libbabeltrace2 not close the shared |
cd4aac1e PP |
1472 | libraries (plugins) which it loads. You need this to see the appropriate |
1473 | backtrace when Valgrind shows errors. |