Commit | Line | Data |
---|---|---|
7704a0af PP |
1 | /*! |
2 | @page api-fund API fundamentals | |
3 | ||
4 | This page explains the basic principles of the \bt_api. | |
5 | ||
6 | You \em must understand what the API expects before you create a | |
7 | \bt_name \bt_plugin or an application which uses the API. | |
8 | ||
9 | @section api-fund-header Header file | |
10 | ||
11 | To use the \bt_api, include <code>%babeltrace2/babeltrace.h</code>: | |
12 | ||
13 | @code | |
14 | #include <babeltrace2/babeltrace.h> | |
15 | @endcode | |
16 | ||
17 | Do \em not include any other header file found in the \c babeltrace2 | |
18 | directory: the compiler prints an error when you try to. | |
19 | ||
20 | @section api-fund-ns Namespace | |
21 | ||
22 | - All libbabeltrace2 functions and types start with \c bt_. | |
23 | ||
24 | - All libbabeltrace2 definitions, macros, and enumerators start | |
25 | with \c BT_. | |
26 | ||
27 | @section api-fund-pre-post Function precondition and postcondition checking | |
28 | ||
29 | All the functions of libbabeltrace2 which have parameters check that | |
30 | the caller meets their | |
31 | <a href="https://en.wikipedia.org/wiki/Precondition">preconditions</a>. | |
32 | ||
33 | All the functions of libbabeltrace2 which call a user function which | |
34 | returns something check that the returned value meets their | |
35 | <a href="https://en.wikipedia.org/wiki/Postcondition">postconditions</a>. | |
36 | ||
37 | The function descriptions in the | |
38 | <a class="el" href="modules.html">API reference modules</a> | |
39 | list all their preconditions and postconditions, if any. | |
40 | ||
41 | libbabeltrace2 is very strict regarding function preconditions and | |
42 | postconditions: when you break any of them, the library prints how the | |
43 | precondition or postcondition was not satisfied, with details, and then | |
44 | calls <code>abort()</code>. | |
45 | ||
46 | Here's an example of what the library prints to the standard error | |
47 | before aborting when you break a precondition: | |
48 | ||
49 | @code{.unparsed} | |
50 | 10-06 09:12:20.228 62362 62362 F LIB/VALUE bt_value_array_get_length@value.c:887 Babeltrace 2 library precondition not satisfied; error is: | |
51 | 10-06 09:12:20.228 62362 62362 F LIB/VALUE bt_value_array_get_length@value.c:887 Value object is NULL: | |
52 | 10-06 09:12:20.228 62362 62362 F LIB/VALUE bt_value_array_get_length@value.c:887 Aborting... | |
53 | @endcode | |
54 | ||
55 | Because precondition and postcondition checks detect programming errors, | |
56 | libbabeltrace2's approach is to abort as soon as possible so that you | |
57 | fix the error. Therefore, the libbabeltrace2 functions never return a | |
58 | programming error status (like what \c EINVAL means on Unix systems, for | |
59 | example). | |
60 | ||
61 | @attention | |
62 | Some precondition and postcondition checks which occur on the fast | |
63 | path and which would therefore significantly impact performance | |
64 | during a typical trace processing \bt_graph run are only enabled in | |
65 | \ref guide-build-bt2-dev "developer mode". | |
66 | ||
67 | Common function preconditions are: | |
68 | ||
69 | - A pointer parameter is not \c NULL. | |
70 | ||
71 | - An index parameter is not ouf of bounds. | |
72 | ||
73 | - A string or container parameter is not empty. | |
74 | ||
75 | - An object parameter has a given conceptual type. For example, you | |
76 | cannot call bt_value_array_get_length() with a | |
77 | \bt_bool_val. | |
78 | ||
79 | - An object parameter is not \ref api-fund-freezing "frozen". | |
80 | ||
81 | - An object parameter has some specific state. | |
82 | ||
83 | @section api-fund-object Object model | |
84 | ||
85 | The \bt_api is | |
86 | <a href="https://en.wikipedia.org/wiki/Object-oriented_programming">object-oriented</a>. | |
87 | ||
88 | With a few exceptions, API functions are actually | |
89 | <a href="https://en.wikipedia.org/wiki/Method_(computer_programming)"><em>methods</em></a> | |
90 | which operate on objects: their first parameter points to said object. | |
91 | For example: | |
92 | ||
93 | @code | |
94 | uint64_t bt_value_array_get_length(const bt_value *value); | |
95 | @endcode | |
96 | ||
97 | You can create some types of objects with functions that contain the | |
98 | word \c create, while for some other types, only the library can create | |
99 | them behind the scenes. For example, you can create a | |
100 | \bt_bool_val object with bt_value_bool_create(), but you cannot directly | |
101 | create a \bt_ev object: you need to borrow one from a \bt_ev_msg which | |
102 | contains it. | |
103 | ||
104 | Each type of object has its own C type. Learn more about typing in | |
105 | \ref api-fund-c-typing below. | |
106 | ||
107 | Some types of objects conceptually inherit other types of objects. If an | |
108 | object type A inherits an object type B, then you can use both the A and | |
109 | B API functions with an object of type A. For example, because an | |
110 | \bt_enum_fc \em is conceptually an \bt_int_fc, you can use any integer | |
111 | field class function with an enumeration field class. | |
112 | The <a class="el" href="modules.html">API reference modules</a> always | |
113 | indicate the inheritance relations. | |
114 | ||
115 | @subsection api-fund-object-shared-unique Shared vs. unique objects | |
116 | ||
117 | Some \bt_name objects are \em shared while some others are \em unique: | |
118 | ||
119 | <dl> | |
120 | <dt>\anchor api-fund-shared-object Shared object</dt> | |
121 | <dd> | |
122 | A \em shared object has a <a | |
123 | href="https://en.wikipedia.org/wiki/Reference_counting">reference | |
124 | count</a>. | |
125 | ||
126 | A shared object's creation function returns a \em new reference. | |
127 | ||
128 | The API of a given shared object type contains: | |
129 | ||
130 | - A function to get a new reference, increasing the reference count, | |
131 | which ends with \c _get_ref. | |
132 | ||
133 | - A function to put an existing reference, decreasing the reference | |
134 | count, which ends with \c _put_ref. | |
135 | ||
136 | - A macro to put an existing reference and then set the passed | |
137 | expression to \c NULL. This macro ends with \c _PUT_REF_AND_RESET. | |
138 | ||
139 | - A macro to move an existing reference from a source expression to | |
140 | a destination expression, putting the destination expression's | |
141 | existing reference, and setting the source expression to \c NULL. | |
142 | This macro ends with \c _MOVE_REF. | |
143 | ||
144 | For example, bt_value_get_ref() and bt_value_put_ref() get and put | |
145 | \bt_val object references, BT_VALUE_PUT_REF_AND_RESET() puts a | |
146 | value reference and sets the expression to \c NULL, and | |
147 | BT_VALUE_MOVE_REF() moves a value reference. | |
148 | ||
149 | All <code>*_get_ref()</code> and <code>*_put_ref()</code> functions, | |
150 | and all <code>*_PUT_REF_AND_RESET()</code> macros accept a \c NULL | |
151 | parameter. | |
152 | ||
153 | When the reference count of a given object reaches zero, it \em can | |
154 | be destroyed. Some shared objects, however, have a lifetime that is | |
155 | managed by another shared object. For example, an \bt_ev_cls is not | |
156 | destroyed until its parent \bt_stream_cls is also destroyed, even if | |
157 | its reference count technically reaches zero. | |
158 | ||
159 | A function which accepts a shared object never "takes" or steals the | |
160 | caller's reference unless its name contains the word \c move: you | |
161 | still have your own reference when the function returns. For | |
162 | example: | |
163 | ||
164 | @code | |
165 | bt_event_class *event_class = bt_event_class_create(stream_class); | |
166 | ||
167 | /* | |
168 | * At this point, we still have a reference of `stream_class`. | |
169 | * We need to put it with bt_stream_class_put_ref() at some point. | |
170 | */ | |
171 | @endcode | |
172 | ||
173 | A function which contains the word \c borrow returns a | |
174 | <em>borrowed reference</em>: if you need your own reference, get | |
175 | one with the appropriate <code>*_get_ref()</code> function. | |
176 | </dd> | |
177 | ||
178 | <dt>\anchor api-fund-unique-object Unique object</dt> | |
179 | <dd> | |
180 | A \em unique object does not have a reference count: another object | |
181 | is always its sole owner. | |
182 | ||
183 | Because you cannot get a new unique object reference, you \em must | |
184 | ensure that you own the unique object's owner to keep it alive. The | |
185 | <a class="el" href="modules.html">API reference modules</a> make it | |
186 | clear, depending on the context, which | |
187 | shared object is the ultimate owner of a given unique object. | |
188 | ||
189 | In general, you cannot create a unique object: the library creates | |
190 | it, and then you \em borrow it from another object (shared or unique | |
191 | itself). | |
192 | ||
193 | Unique objects exist for performance reasons: some optimizations are | |
194 | challenging to implement without this concept. | |
195 | </dd> | |
196 | </dl> | |
197 | ||
198 | In the <a class="el" href="modules.html">API reference</a>, each module | |
199 | indicates whether the documented objects are shared or unique. | |
200 | ||
201 | @subsection api-fund-freezing Object freezing | |
202 | ||
203 | The library can \em freeze some types of \bt_name objects when specific | |
204 | functions succeed. | |
205 | ||
206 | A frozen object is immutable: trying to set an object's property once | |
207 | it's frozen represents a \ref api-fund-pre-post "precondition" break. | |
208 | ||
209 | For example, the library freezes the source \bt_comp initialization | |
210 | parameters when you call bt_graph_add_source_component(): this | |
211 | guarantees to the component's | |
212 | \ref api-comp-cls-dev-meth-init "initialization method" that the | |
213 | parameters will never change for the rest of their lifetime. | |
214 | ||
215 | When an object becomes frozen, its contained objects, if any, also | |
216 | become frozen, recursively. | |
217 | ||
218 | There's no function to check whether or not a given object is frozen. | |
219 | Because the <a class="el" href="modules.html">API reference modules</a> | |
220 | document which functions freeze which objects, | |
221 | the "frozen" property is only useful for libbabeltrace2 to catch | |
222 | programming errors (\ref api-fund-pre-post "precondition checks"). | |
223 | ||
224 | @attention | |
225 | Some "frozen" property checks which occur on the fast path and which | |
226 | would therefore significantly impact performance during a typical trace | |
227 | processing \bt_graph run are only enabled in | |
228 | \ref guide-build-bt2-dev "developer mode". | |
229 | ||
230 | @section api-fund-c-typing C typing | |
231 | ||
232 | The \bt_api typing system is very strict to catch many programming | |
233 | errors at compile time. | |
234 | ||
235 | Each type of object has its own C type. Consequently, functions accept | |
236 | and return specific C types. For example, all the \bt_ev functions | |
237 | accept a #bt_event pointer. | |
238 | ||
239 | The API uses | |
240 | <a href="https://en.wikipedia.org/wiki/Opaque_pointer">opaque pointers</a>, | |
241 | so that you don't having access to the object type's actual C structure. | |
242 | This helps with the development of features and fixes in future releases | |
243 | of \bt_name. | |
244 | ||
245 | Some objects share the same C type when different conceptual types can | |
246 | be contained in some collection. For example, all \bt_val objects have | |
247 | the type #bt_value because an \bt_array_val can contain different | |
248 | types of values. You must be careful to only call the functions which | |
249 | apply to a specific type of such objects. | |
250 | The <a class="el" href="modules.html">API reference modules</a> make | |
251 | this clear in the precondition section. Such objects always have a | |
252 | <code>*_get_type()</code> function to get the object's exact type | |
253 | enumerator. For example, bt_value_get_type() returns the type enumerator | |
254 | of a given \bt_val object. | |
255 | ||
256 | When an object type A conceptually inherits an object type B, and when A | |
257 | and B have different C types, the API offers a dedicated, inline | |
258 | upcasting function named <code>bt_A_as_B()</code> to have access to the B | |
259 | API at no cost. For example, an \bt_uenum_fc mapping \em is conceptually | |
260 | an \bt_enum_fc mapping, but they have different C types: | |
261 | #bt_field_class_enumeration_unsigned_mapping and | |
262 | #bt_field_class_enumeration_mapping. Get the latter from the former with | |
263 | bt_field_class_enumeration_unsigned_mapping_as_mapping_const(). | |
264 | The <code>bt_A_as_B()</code> functions do not change the object's | |
265 | reference count and they accept \c NULL. | |
266 | ||
267 | @attention | |
268 | \b Never directly cast a \bt_name object pointer from some C type to | |
269 | another C type: the API is designed so that you never need to do | |
270 | that. | |
271 | ||
272 | @subsection api-fund-const const correctness | |
273 | ||
274 | The \bt_api is <code>const</code>-correct: when a function has a | |
275 | \c const object pointer parameter, it never modifies that object from | |
276 | the user's viewpoint. | |
277 | ||
278 | As such, when a function returns a \c const object pointer, directly or | |
279 | through an output parameter, you can't modify the object. | |
280 | ||
281 | @attention | |
282 | \b Never remove a \bt_name object pointer's \c const qualifier. The | |
283 | API is designed so that you never need to do that. | |
284 | ||
285 | Functions which accept or return a \c const object pointer end with | |
286 | \c _const when they have (or could have in the future) a non \c const | |
287 | equivalent. For example, bt_value_map_borrow_entry_value_const() is the | |
288 | \c const version of bt_value_map_borrow_entry_value(). | |
289 | ||
290 | Simple property getter functions do not end with \c _const. | |
291 | ||
292 | \ref api-fund-shared-object "Reference count" changing functions, ending | |
293 | with \c _get_ref and \c _put_ref(), accept a \c const object pointer | |
294 | parameter: the library does not consider that an object's nature is | |
295 | altered when its reference count changes. | |
296 | ||
297 | @subsection api-fund-int-types C integer types | |
298 | ||
299 | The API only uses \c uint64_t and \c int64_t as C integer types for | |
300 | clarity and consistency. | |
301 | ||
302 | @subsection api-fund-common-types Common C types and definitions | |
303 | ||
304 | There are a few C types and definitions which are common to many parts | |
305 | of the \bt_api. | |
306 | ||
307 | See \ref api-common-types. | |
308 | ||
309 | @section api-fund-func-status Function return | |
310 | ||
311 | libbabeltrace2 functions which cannot fail return a property or an | |
312 | object pointer directly. For example, bt_value_array_get_length() | |
313 | returns the length of an \bt_array_val, and | |
314 | bt_value_array_borrow_element_by_index_const() returns a \bt_val | |
315 | contained in an \bt_array_val. Both functions cannot fail: any | |
316 | programming error \ref api-fund-pre-post "makes the program abort". | |
317 | ||
318 | When a function returns an optional property or object: | |
319 | ||
320 | <dl> | |
321 | <dt>If it's a pointer</dt> | |
322 | <dd> | |
323 | The function returns \c NULL if the property/object is missing. | |
324 | </dd> | |
325 | ||
326 | <dt>If it's not a pointer</dt> | |
327 | <dd> | |
328 | <dl> | |
329 | <dt>If the property is available</dt> | |
330 | <dd> | |
331 | The function returns the property by output parameter and returns | |
332 | #BT_PROPERTY_AVAILABILITY_AVAILABLE. | |
333 | </dd> | |
334 | ||
335 | <dt>If the property is not available</dt> | |
336 | <dd> | |
337 | The function returns #BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE. | |
338 | </dd> | |
339 | </dl> | |
340 | </dd> | |
341 | </dl> | |
342 | ||
343 | Many libbabeltrace2 functions return a status code, that is, a C | |
344 | enumerator containing the word \c STATUS. For example, | |
345 | bt_value_copy() returns either #BT_VALUE_COPY_STATUS_OK or | |
346 | #BT_VALUE_COPY_STATUS_MEMORY_ERROR. | |
347 | ||
348 | Although the API guarantees that any status enumerator which has the | |
349 | \c _OK status has the value 0, we recommend that you compare the | |
350 | returned value to exact status enumerators for clarity, for example: | |
351 | ||
352 | @code | |
353 | bt_value_copy_status status = bt_value_copy(obj, &val_copy); | |
354 | ||
355 | if (status != BT_VALUE_COPY_STATUS_OK) { | |
356 | /* handle error */ | |
357 | } | |
358 | @endcode | |
359 | ||
360 | The <a class="el" href="modules.html">API reference modules</a> | |
361 | document, for each function, what each return status enumerator means. | |
362 | ||
363 | Some functions return properties or objects by output parameter. When | |
364 | such a function which accepts a property or object pointer \c ptr fails, | |
365 | the library does \em not guarantee that <code>*ptr</code> remains | |
366 | unchanged. Therefore, such a pattern is \em not safe: | |
367 | ||
368 | @code | |
369 | bt_some_object *some_object = NULL; | |
370 | ||
371 | status = bt_get_some_object(obj, &some_object); | |
372 | ||
373 | if (some_object) { | |
374 | /* ... */ | |
375 | } | |
376 | @endcode | |
377 | ||
378 | Always rely on the returned status code: | |
379 | ||
380 | @code | |
381 | bt_some_object *some_object; | |
382 | ||
383 | status = bt_get_some_object(obj, &some_object); | |
384 | ||
385 | if (status == BT_GET_SOME_OBJECT_STATUS_OK) { | |
386 | /* ... */ | |
387 | } | |
388 | @endcode | |
389 | ||
390 | @section api-fund-user-classes User classes | |
391 | ||
392 | The whole \bt_name project is about extensibility: you can implement | |
393 | \bt_p_comp_cls, and then package and distribute them as | |
394 | \bt_p_plugin. | |
395 | ||
396 | When you implement a \bt_name \bt_comp_cls, you override protected | |
397 | methods, just like you would do in any | |
398 | <a href="https://en.wikipedia.org/wiki/Object-oriented_programming">object-oriented programming</a> | |
399 | (OOP) language. | |
400 | ||
401 | Here's the mapping of typical OOP language features to the | |
402 | \bt_name library domain: | |
403 | ||
404 | <table> | |
405 | <tr> | |
406 | <th>OOP concept | |
407 | <th>\bt_name equivalent | |
408 | <tr> | |
409 | <td>User class. | |
410 | <td> | |
411 | Class object with implemented user functions. | |
412 | ||
413 | For example: #bt_component_class_source. | |
414 | <tr> | |
415 | <td>User class instance. | |
416 | <td> | |
417 | Instance object, created from a class object. | |
418 | ||
419 | For example: #bt_component_source. | |
420 | <tr> | |
421 | <td> | |
422 | Instance pointer (\c this keyword in C++/Java and \c self variable | |
423 | in Python, for example). | |
424 | <td> | |
425 | "Self" (private) object. | |
426 | ||
427 | A "self" object has a specific, dedicated C type which starts | |
428 | with <code>bt_self_</code>. | |
429 | ||
430 | For example: #bt_self_component_source. | |
431 | <tr> | |
432 | <td>Protected, final method. | |
433 | <td> | |
434 | Library function accepting an instance pointer ("self" object) as | |
435 | its first parameter. | |
436 | ||
437 | Those functions always start with <code>bt_self_</code>. | |
438 | ||
439 | For example: bt_self_component_source_add_output_port(). | |
440 | <tr> | |
441 | <td>Protected, overridable method. | |
442 | <td> | |
443 | User function with a specific signature, accepting an instance | |
444 | pointer ("self" object) as its first parameter. | |
445 | ||
446 | For example: #bt_component_class_source_initialize_method. | |
447 | <tr> | |
448 | <td>Private user method. | |
449 | <td> | |
450 | Custom \c static user function having access to the instance | |
451 | pointer ("self" object) somehow. | |
452 | <tr> | |
453 | <td>Private user property or attribute. | |
454 | <td> | |
455 | Custom \bt_voidp data which you set and get using | |
456 | dedicated protected methods (for example, | |
457 | bt_self_component_set_data() and bt_self_component_get_data()). | |
458 | </table> | |
459 | ||
460 | @section api-fund-error Error reporting | |
461 | ||
462 | libbabeltrace2 features a rich \ref api-error "error reporting" | |
463 | mechanism to augment an error with custom causes without having to | |
464 | explicitly pass an error object to the library functions. | |
465 | ||
466 | When a library function or \ref api-fund-user-classes "user method" | |
467 | returns an error status code (any status enumerator which contains | |
468 | the word \c ERROR), it \em can add one or more error causes to the | |
469 | current thread's error object. | |
470 | ||
471 | This makes it possible for the end user to understand the contexts which | |
472 | lead to the error, possibly across many \bt_p_plugin written by | |
473 | different developers. | |
474 | ||
475 | An error cause contains information about the source location where the | |
fe5ee428 | 476 | error occurred, the actor involved in the error, and a message. |
7704a0af PP |
477 | |
478 | When you "catch" an error, that is, react to a function returning an | |
479 | error status code without returning an error status code yourself, | |
480 | you can: | |
481 | ||
482 | - Take the current thread's error with bt_current_thread_take_error() to | |
483 | get its causes, possibly presenting them to the end user. | |
484 | ||
485 | You then need to release the error with bt_error_release(). | |
486 | ||
487 | - Clear the current thread's error with bt_current_thread_clear_error(). | |
488 | ||
489 | @attention | |
490 | You \em cannot call any libbabeltrace2 function when the current | |
491 | thread has an error, except the | |
492 | \ref api-fund-shared-object "reference counting" functions (ending | |
493 | with <code>_get_ref()</code> or <code>_put_ref()</code>). | |
494 | ||
495 | The | |
496 | <a href="https://babeltrace.org/docs/v\bt_version_min_maj/man1/babeltrace2.1"><code>babeltrace2</code></a> | |
497 | CLI uses this feature to pretty-print an error's causes to the end user, | |
498 | for example: | |
499 | ||
500 | @code{.unparsed} | |
501 | ERROR: [Babeltrace CLI] (babeltrace2.c:2521) | |
502 | Cannot create components. | |
503 | CAUSED BY [Babeltrace CLI] (babeltrace2.c:2336) | |
504 | Cannot create component: plugin-name="ctf", comp-cls-name="fs", comp-cls-type=0, | |
505 | comp-name="auto-disc-source-ctf-fs" | |
506 | CAUSED BY [libbabeltrace2] (graph.c:1343) | |
507 | Component initialization method failed: status=ERROR, comp-addr=0x562fbd275f40, | |
508 | comp-name="auto-disc-source-ctf-fs", comp-log-level=WARNING, comp-class-type=SOURCE, | |
509 | comp-class-name="fs", comp-class-partial-descr="Read CTF traces from the file sy", | |
510 | comp-class-is-frozen=1, comp-class-so-handle-addr=0x562fbd285810, | |
511 | comp-class-so-handle-path="/usr/lib/babeltrace2/plugins/babeltrace-plugin-ctf.so", | |
512 | comp-input-port-count=0, comp-output-port-count=0 | |
513 | CAUSED BY [auto-disc-source-ctf-fs: 'source.ctf.fs'] (fs.c:1148) | |
514 | Cannot create trace for `/path/to/trace`. | |
515 | CAUSED BY [auto-disc-source-ctf-fs: 'source.ctf.fs'] (fs.c:928) | |
516 | Cannot add stream file `/path/to/trace/channel0_1` to stream file group | |
517 | CAUSED BY [auto-disc-source-ctf-fs: 'source.ctf.fs'] (fs.c:734) | |
518 | Cannot get stream file's first packet's header and context fields (`/path/to/trace/channel0_1`). | |
519 | @endcode | |
520 | ||
521 | @section api-fund-logging Logging | |
522 | ||
523 | libbabeltrace2 contains many hundreds of logging statements to help you | |
524 | follow and debug your \bt_plugin or program. | |
525 | ||
526 | By default, the library's logging is disabled. To enable it, use | |
527 | bt_logging_set_global_level(). | |
528 | ||
529 | To set the library's initial logging level (checked once at library | |
530 | loading time), set the \c LIBBABELTRACE2_INIT_LOG_LEVEL environment | |
531 | variable, with one of: | |
532 | ||
533 | - \c N or \c NONE | |
534 | - \c F or \c FATAL | |
535 | - \c E or \c ERROR | |
536 | - \c W, \c WARN, or \c WARNING | |
537 | - \c I or \c INFO | |
538 | - \c D or \c DEBUG | |
539 | - \c T or \c TRACE | |
540 | ||
541 | By default, the minimal, build-time logging level is \em DEBUG. We | |
542 | recommend that you build libbabeltrace2 with the \em TRACE minimal | |
543 | logging level for development. See \ref guide-build-bt2-dev. | |
544 | ||
545 | libbabeltrace2 writes its logging statements to the standard error | |
546 | stream. | |
547 | ||
548 | A libbabeltrace2 (and \bt_name project plugin) logging line looks like | |
549 | this: | |
550 | ||
551 | @code{.unparsed} | |
552 | 05-11 00:58:03.691 23402 23402 D VALUES bt_value_destroy@values.c:498 Destroying value: addr=0xb9c3eb0 | |
553 | @endcode | |
554 | ||
555 | The line contains, in order: | |
556 | ||
557 | -# The date and time (<code>05-11 00:58:03.691</code>). | |
558 | ||
559 | -# The process and thread IDs (<code>23402 23402</code>). | |
560 | ||
561 | -# The logging level (\c D for \em DEBUG). | |
562 | ||
563 | -# The function logging (\c bt_value_destroy). | |
564 | ||
565 | -# The file and line number logging (<code>values.c:498</code>). | |
566 | ||
567 | -# The message, which typically ends with a list of fields adding | |
568 | details. | |
569 | */ |