Rename `BT_LOG_LEVEL` -> `BT_MINIMAL_LOG_LEVEL`
[babeltrace.git] / src / logging / log.h
1 /*
2 * This is zf_log.h, modified with Babeltrace prefixes.
3 * See <https://github.com/wonder-mice/zf_log/>.
4 * See logging/LICENSE in the Babeltrace source tree.
5 */
6
7 #pragma once
8
9 #ifndef BABELTRACE_LOGGING_INTERNAL_H
10 #define BABELTRACE_LOGGING_INTERNAL_H
11
12 #include <errno.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <babeltrace2/logging.h>
17 #include "common/macros.h"
18 #include "common/assert.h"
19
20 /* To detect incompatible changes you can define BT_LOG_VERSION_REQUIRED to be
21 * the current value of BT_LOG_VERSION before including this file (or via
22 * compiler command line):
23 *
24 * #define BT_LOG_VERSION_REQUIRED 4
25 * #include "logging.h"
26 *
27 * Compilation will fail when included file has different version.
28 */
29 #define BT_LOG_VERSION 4
30 #if defined(BT_LOG_VERSION_REQUIRED)
31 #if BT_LOG_VERSION_REQUIRED != BT_LOG_VERSION
32 #error different bt_log version required
33 #endif
34 #endif
35
36 /* Log level guideline:
37 * - BT_LOG_FATAL - happened something impossible and absolutely unexpected.
38 * Process can't continue and must be terminated.
39 * Example: division by zero, unexpected modifications from other thread.
40 * - BT_LOG_ERROR - happened something possible, but highly unexpected. The
41 * process is able to recover and continue execution.
42 * Example: out of memory (could also be FATAL if not handled properly).
43 * - BT_LOG_WARN - happened something that *usually* should not happen and
44 * significantly changes application behavior for some period of time.
45 * Example: configuration file not found, auth error.
46 * - BT_LOG_INFO - happened significant life cycle event or major state
47 * transition.
48 * Example: app started, user logged in.
49 * - BT_LOG_DEBUG - minimal set of events that could help to reconstruct the
50 * execution path. Usually disabled in release builds.
51 * - BT_LOG_TRACE - all other events. Usually disabled in release builds.
52 *
53 * *Ideally*, log file of debugged, well tested, production ready application
54 * should be empty or very small. Choosing a right log level is as important as
55 * providing short and self descriptive log message.
56 */
57 #define BT_LOG_TRACE BT_LOGGING_LEVEL_TRACE
58 #define BT_LOG_DEBUG BT_LOGGING_LEVEL_DEBUG
59 #define BT_LOG_INFO BT_LOGGING_LEVEL_INFO
60 #define BT_LOG_WARN BT_LOGGING_LEVEL_WARN
61 #define BT_LOG_ERROR BT_LOGGING_LEVEL_ERROR
62 #define BT_LOG_FATAL BT_LOGGING_LEVEL_FATAL
63 #define BT_LOG_NONE BT_LOGGING_LEVEL_NONE
64
65 /* "Current" log level is a compile time check and has no runtime overhead. Log
66 * level that is below current log level it said to be "disabled".
67 * Otherwise, it's "enabled". Log messages that are disabled has no
68 * runtime overhead - they are converted to no-op by preprocessor and
69 * then eliminated by compiler. Current log level is configured per
70 * compilation module (.c/.cpp/.m file) by defining BT_LOG_DEF_LEVEL or
71 * BT_MINIMAL_LOG_LEVEL. BT_MINIMAL_LOG_LEVEL has higer priority and
72 * when defined overrides value provided by BT_LOG_DEF_LEVEL.
73 *
74 * Common practice is to define default current log level with BT_LOG_DEF_LEVEL
75 * in build script (e.g. Makefile, CMakeLists.txt, gyp, etc.) for the entire
76 * project or target:
77 *
78 * CC_ARGS := -DBT_LOG_DEF_LEVEL=BT_LOG_INFO
79 *
80 * And when necessary to override it with BT_MINIMAL_LOG_LEVEL in .c/.cpp/.m files
81 * before including bt_log.h:
82 *
83 * #define BT_MINIMAL_LOG_LEVEL BT_LOG_TRACE
84 * #include "logging.h"
85 *
86 * If both BT_LOG_DEF_LEVEL and BT_MINIMAL_LOG_LEVEL are undefined, then
87 * BT_LOG_INFO will be used for release builds (BT_DEBUG_MODE is NOT
88 * defined) and BT_LOG_DEBUG otherwise (BT_DEBUG_MODE is defined).
89 */
90 #if defined(BT_MINIMAL_LOG_LEVEL)
91 #define _BT_MINIMAL_LOG_LEVEL BT_MINIMAL_LOG_LEVEL
92 #elif defined(BT_LOG_DEF_LEVEL)
93 #define _BT_MINIMAL_LOG_LEVEL BT_LOG_DEF_LEVEL
94 #else
95 #ifdef BT_DEBUG_MODE
96 #define _BT_MINIMAL_LOG_LEVEL BT_LOG_DEBUG
97 #else
98 #define _BT_MINIMAL_LOG_LEVEL BT_LOG_INFO
99 #endif
100 #endif
101
102 /* "Output" log level is a runtime check. When log level is below output log
103 * level it said to be "turned off" (or just "off" for short). Otherwise
104 * it's "turned on" (or just "on"). Log levels that were "disabled" (see
105 * BT_MINIMAL_LOG_LEVEL and BT_LOG_DEF_LEVEL) can't be "turned on", but
106 * "enabled" log levels could be "turned off". Only messages with log
107 * level which is "turned on" will reach output facility. All other
108 * messages will be ignored (and their arguments will not be evaluated).
109 * Output log level is a global property and configured per process
110 * using bt_log_set_output_level() function which can be called at any
111 * time.
112 *
113 * Though in some cases it could be useful to configure output log level per
114 * compilation module or per library. There are two ways to achieve that:
115 * - Define BT_LOG_OUTPUT_LEVEL to expresion that evaluates to desired output
116 * log level.
117 * - Copy bt_log.h and bt_log.c files into your library and build it with
118 * BT_LOG_LIBRARY_PREFIX defined to library specific prefix. See
119 * BT_LOG_LIBRARY_PREFIX for more details.
120 *
121 * When defined, BT_LOG_OUTPUT_LEVEL must evaluate to integral value
122 * that corresponds to desired output log level. Use it only when
123 * compilation module is required to have output log level which is
124 * different from global output log level set by
125 * bt_log_set_output_level() function. For other cases, consider
126 * defining BT_MINIMAL_LOG_LEVEL or using bt_log_set_output_level()
127 * function.
128 *
129 * Example:
130 *
131 * #define BT_LOG_OUTPUT_LEVEL g_module_log_level
132 * #include "logging.h"
133 * static int g_module_log_level = BT_LOG_INFO;
134 * static void foo() {
135 * BT_LOGI("Will check g_module_log_level for output log level");
136 * }
137 * void debug_log(bool on) {
138 * g_module_log_level = on? BT_LOG_DEBUG: BT_LOG_INFO;
139 * }
140 *
141 * Note on performance. This expression will be evaluated each time
142 * message is logged (except when message log level is "disabled" - see
143 * BT_MINIMAL_LOG_LEVEL for details). Keep this expression as simple as
144 * possible, otherwise it will not only add runtime overhead, but also
145 * will increase size of call site (which will result in larger
146 * executable). The prefered way is to use integer variable (as in
147 * example above). If structure must be used, log_level field must be
148 * the first field in this structure:
149 *
150 * #define BT_LOG_OUTPUT_LEVEL (g_config.log_level)
151 * #include "logging.h"
152 * struct config {
153 * int log_level;
154 * unsigned other_field;
155 * [...]
156 * };
157 * static config g_config = {BT_LOG_INFO, 0, ...};
158 *
159 * This allows compiler to generate more compact load instruction (no need to
160 * specify offset since it's zero). Calling a function to get output log level
161 * is generaly a bad idea, since it will increase call site size and runtime
162 * overhead even further.
163 */
164 #if defined(BT_LOG_OUTPUT_LEVEL)
165 #define _BT_LOG_OUTPUT_LEVEL BT_LOG_OUTPUT_LEVEL
166 #else
167 /*
168 * We disallow this to make sure Babeltrace modules always
169 * have their own local log level.
170 */
171 #error No log level symbol specified: please define BT_LOG_OUTPUT_LEVEL before including this header.
172 #endif
173
174 /* "Tag" is a compound string that could be associated with a log message. It
175 * consists of tag prefix and tag (both are optional).
176 *
177 * Tag prefix is a global property and configured per process using
178 * bt_log_set_tag_prefix() function. Tag prefix identifies context in which
179 * component or module is running (e.g. process name). For example, the same
180 * library could be used in both client and server processes that work on the
181 * same machine. Tag prefix could be used to easily distinguish between them.
182 * For more details about tag prefix see bt_log_set_tag_prefix() function. Tag
183 * prefix
184 *
185 * Tag identifies component or module. It is configured per compilation module
186 * (.c/.cpp/.m file) by defining BT_LOG_TAG or BT_LOG_DEF_TAG. BT_LOG_TAG has
187 * higer priority and when defined overrides value provided by BT_LOG_DEF_TAG.
188 * When defined, value must evaluate to (const char *), so for strings double
189 * quotes must be used.
190 *
191 * Default tag could be defined with BT_LOG_DEF_TAG in build script (e.g.
192 * Makefile, CMakeLists.txt, gyp, etc.) for the entire project or target:
193 *
194 * CC_ARGS := -DBT_LOG_DEF_TAG=\"MISC\"
195 *
196 * And when necessary could be overriden with BT_LOG_TAG in .c/.cpp/.m files
197 * before including bt_log.h:
198 *
199 * #define BT_LOG_TAG "MAIN"
200 * #include "logging.h"
201 *
202 * If both BT_LOG_DEF_TAG and BT_LOG_TAG are undefined no tag will be added to
203 * the log message (tag prefix still could be added though).
204 *
205 * Output example:
206 *
207 * 04-29 22:43:20.244 40059 1299 I hello.MAIN Number of arguments: 1
208 * | |
209 * | +- tag (e.g. module)
210 * +- tag prefix (e.g. process name)
211 */
212 #if defined(BT_LOG_TAG)
213 #define _BT_LOG_TAG BT_LOG_TAG
214 #elif defined(BT_LOG_DEF_TAG)
215 #define _BT_LOG_TAG BT_LOG_DEF_TAG
216 #else
217 #define _BT_LOG_TAG 0
218 #endif
219
220 /* Source location is part of a log line that describes location (function or
221 * method name, file name and line number, e.g. "runloop@main.cpp:68") of a
222 * log statement that produced it.
223 * Source location formats are:
224 * - BT_LOG_SRCLOC_NONE - don't add source location to log line.
225 * - BT_LOG_SRCLOC_SHORT - add source location in short form (file and line
226 * number, e.g. "@main.cpp:68").
227 * - BT_LOG_SRCLOC_LONG - add source location in long form (function or method
228 * name, file and line number, e.g. "runloop@main.cpp:68").
229 */
230 #define BT_LOG_SRCLOC_NONE 0
231 #define BT_LOG_SRCLOC_SHORT 1
232 #define BT_LOG_SRCLOC_LONG 2
233
234 /* Source location format is configured per compilation module (.c/.cpp/.m
235 * file) by defining BT_LOG_DEF_SRCLOC or BT_LOG_SRCLOC. BT_LOG_SRCLOC has
236 * higer priority and when defined overrides value provided by
237 * BT_LOG_DEF_SRCLOC.
238 *
239 * Common practice is to define default format with BT_LOG_DEF_SRCLOC in
240 * build script (e.g. Makefile, CMakeLists.txt, gyp, etc.) for the entire
241 * project or target:
242 *
243 * CC_ARGS := -DBT_LOG_DEF_SRCLOC=BT_LOG_SRCLOC_LONG
244 *
245 * And when necessary to override it with BT_LOG_SRCLOC in .c/.cpp/.m files
246 * before including bt_log.h:
247 *
248 * #define BT_LOG_SRCLOC BT_LOG_SRCLOC_NONE
249 * #include "logging.h"
250 *
251 * If both BT_LOG_DEF_SRCLOC and BT_LOG_SRCLOC are undefined, then
252 * BT_LOG_SRCLOC_NONE will be used for release builds (BT_DEBUG_MODE is
253 * NOT defined) and BT_LOG_SRCLOC_LONG otherwise (BT_DEBUG_MODE is
254 * defined).
255 */
256 #if defined(BT_LOG_SRCLOC)
257 #define _BT_LOG_SRCLOC BT_LOG_SRCLOC
258 #elif defined(BT_LOG_DEF_SRCLOC)
259 #define _BT_LOG_SRCLOC BT_LOG_DEF_SRCLOC
260 #else
261 #ifdef BT_DEBUG_MODE
262 #define _BT_LOG_SRCLOC BT_LOG_SRCLOC_LONG
263 #else
264 #define _BT_LOG_SRCLOC BT_LOG_SRCLOC_NONE
265 #endif
266 #endif
267 #if BT_LOG_SRCLOC_LONG == _BT_LOG_SRCLOC
268 #define _BT_LOG_SRCLOC_FUNCTION _BT_LOG_FUNCTION
269 #else
270 #define _BT_LOG_SRCLOC_FUNCTION 0
271 #endif
272
273 /* Censoring provides conditional logging of secret information, also known as
274 * Personally Identifiable Information (PII) or Sensitive Personal Information
275 * (SPI). Censoring can be either enabled (BT_LOG_CENSORED) or disabled
276 * (BT_LOG_UNCENSORED). When censoring is enabled, log statements marked as
277 * "secrets" will be ignored and will have zero overhead (arguments also will
278 * not be evaluated).
279 */
280 #define BT_LOG_CENSORED 1
281 #define BT_LOG_UNCENSORED 0
282
283 /* Censoring is configured per compilation module (.c/.cpp/.m file) by defining
284 * BT_LOG_DEF_CENSORING or BT_LOG_CENSORING. BT_LOG_CENSORING has higer priority
285 * and when defined overrides value provided by BT_LOG_DEF_CENSORING.
286 *
287 * Common practice is to define default censoring with BT_LOG_DEF_CENSORING in
288 * build script (e.g. Makefile, CMakeLists.txt, gyp, etc.) for the entire
289 * project or target:
290 *
291 * CC_ARGS := -DBT_LOG_DEF_CENSORING=BT_LOG_CENSORED
292 *
293 * And when necessary to override it with BT_LOG_CENSORING in .c/.cpp/.m files
294 * before including bt_log.h (consider doing it only for debug purposes and be
295 * very careful not to push such temporary changes to source control):
296 *
297 * #define BT_LOG_CENSORING BT_LOG_UNCENSORED
298 * #include "logging.h"
299 *
300 * If both BT_LOG_DEF_CENSORING and BT_LOG_CENSORING are undefined, then
301 * BT_LOG_CENSORED will be used for release builds (BT_DEBUG_MODE is NOT
302 * defined) and BT_LOG_UNCENSORED otherwise (BT_DEBUG_MODE is defined).
303 */
304 #if defined(BT_LOG_CENSORING)
305 #define _BT_LOG_CENSORING BT_LOG_CENSORING
306 #elif defined(BT_LOG_DEF_CENSORING)
307 #define _BT_LOG_CENSORING BT_LOG_DEF_CENSORING
308 #else
309 #ifdef BT_DEBUG_MODE
310 #define _BT_LOG_CENSORING BT_LOG_UNCENSORED
311 #else
312 #define _BT_LOG_CENSORING BT_LOG_CENSORED
313 #endif
314 #endif
315
316 /* Check censoring at compile time. Evaluates to true when censoring is disabled
317 * (i.e. when secrets will be logged). For example:
318 *
319 * #if BT_LOG_SECRETS
320 * char ssn[16];
321 * getSocialSecurityNumber(ssn);
322 * BT_LOGI("Customer ssn: %s", ssn);
323 * #endif
324 *
325 * See BT_LOG_SECRET() macro for a more convenient way of guarding single log
326 * statement.
327 */
328 #define BT_LOG_SECRETS (BT_LOG_UNCENSORED == _BT_LOG_CENSORING)
329
330 /* Static (compile-time) initialization support allows to configure logging
331 * before entering main() function. This mostly useful in C++ where functions
332 * and methods could be called during initialization of global objects. Those
333 * functions and methods could record log messages too and for that reason
334 * static initialization of logging configuration is customizable.
335 *
336 * Macros below allow to specify values to use for initial configuration:
337 * - BT_LOG_EXTERN_TAG_PREFIX - tag prefix (default: none)
338 * - BT_LOG_EXTERN_GLOBAL_FORMAT - global format options (default: see
339 * BT_LOG_MEM_WIDTH in bt_log.c)
340 * - BT_LOG_EXTERN_GLOBAL_OUTPUT - global output facility (default: stderr or
341 * platform specific, see BT_LOG_USE_XXX macros in bt_log.c)
342 * - BT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL - global output log level (default: 0 -
343 * all levals are "turned on")
344 *
345 * For example, in log_config.c:
346 *
347 * #include "logging.h"
348 * BT_LOG_DEFINE_TAG_PREFIX = "MyApp";
349 * BT_LOG_DEFINE_GLOBAL_FORMAT = {CUSTOM_MEM_WIDTH};
350 * BT_LOG_DEFINE_GLOBAL_OUTPUT = {BT_LOG_PUT_STD, custom_output_callback, 0};
351 * BT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL = BT_LOG_INFO;
352 *
353 * However, to use any of those macros bt_log library must be compiled with
354 * following macros defined:
355 * - to use BT_LOG_DEFINE_TAG_PREFIX define BT_LOG_EXTERN_TAG_PREFIX
356 * - to use BT_LOG_DEFINE_GLOBAL_FORMAT define BT_LOG_EXTERN_GLOBAL_FORMAT
357 * - to use BT_LOG_DEFINE_GLOBAL_OUTPUT define BT_LOG_EXTERN_GLOBAL_OUTPUT
358 * - to use BT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL define
359 * BT_LOG_EXTERN_GLOBAL_OUTPUT_LEVEL
360 *
361 * When bt_log library compiled with one of BT_LOG_EXTERN_XXX macros defined,
362 * corresponding BT_LOG_DEFINE_XXX macro MUST be used exactly once somewhere.
363 * Otherwise build will fail with link error (undefined symbol).
364 */
365 #define BT_LOG_DEFINE_TAG_PREFIX BT_HIDDEN const char *_bt_log_tag_prefix
366 #define BT_LOG_DEFINE_GLOBAL_FORMAT BT_HIDDEN bt_log_format _bt_log_global_format
367 #define BT_LOG_DEFINE_GLOBAL_OUTPUT BT_HIDDEN bt_log_output _bt_log_global_output
368 #define BT_LOG_DEFINE_GLOBAL_OUTPUT_LEVEL BT_HIDDEN int _bt_log_global_output_lvl
369
370 /* Pointer to global format options. Direct modification is not allowed. Use
371 * bt_log_set_mem_width() instead. Could be used to initialize bt_log_spec
372 * structure:
373 *
374 * const bt_log_output g_output = {BT_LOG_PUT_STD, output_callback, 0};
375 * const bt_log_spec g_spec = {BT_LOG_GLOBAL_FORMAT, &g_output};
376 * BT_LOGI_AUX(&g_spec, "Hello");
377 */
378 #define BT_LOG_GLOBAL_FORMAT ((const bt_log_format *)&_bt_log_global_format)
379
380 /* Pointer to global output variable. Direct modification is not allowed. Use
381 * bt_log_set_output_v() or bt_log_set_output_p() instead. Could be used to
382 * initialize bt_log_spec structure:
383 *
384 * const bt_log_format g_format = {40};
385 * const bt_log_spec g_spec = {g_format, BT_LOG_GLOBAL_OUTPUT};
386 * BT_LOGI_AUX(&g_spec, "Hello");
387 */
388 #define BT_LOG_GLOBAL_OUTPUT ((const bt_log_output *)&_bt_log_global_output)
389
390 /* When defined, all library symbols produced by linker will be prefixed with
391 * provided value. That allows to use bt_log library privately in another
392 * libraries without exposing bt_log symbols in their original form (to avoid
393 * possible conflicts with other libraries / components that also could use
394 * bt_log for logging). Value must be without quotes, for example:
395 *
396 * CC_ARGS := -DBT_LOG_LIBRARY_PREFIX=my_lib_
397 *
398 * Note, that in this mode BT_LOG_LIBRARY_PREFIX must be defined when building
399 * bt_log library AND it also must be defined to the same value when building
400 * a library that uses it. For example, consider fictional KittyHttp library
401 * that wants to use bt_log for logging. First approach that could be taken is
402 * to add bt_log.h and bt_log.c to the KittyHttp's source code tree directly.
403 * In that case it will be enough just to define BT_LOG_LIBRARY_PREFIX in
404 * KittyHttp's build script:
405 *
406 * // KittyHttp/CMakeLists.txt
407 * target_compile_definitions(KittyHttp PRIVATE
408 * "BT_LOG_LIBRARY_PREFIX=KittyHttp_")
409 *
410 * If KittyHttp doesn't want to include bt_log source code in its source tree
411 * and wants to build bt_log as a separate library than bt_log library must be
412 * built with BT_LOG_LIBRARY_PREFIX defined to KittyHttp_ AND KittyHttp library
413 * itself also needs to define BT_LOG_LIBRARY_PREFIX to KittyHttp_. It can do
414 * so either in its build script, as in example above, or by providing a
415 * wrapper header that KittyHttp library will need to use instead of bt_log.h:
416 *
417 * // KittyHttpLogging.h
418 * #define BT_LOG_LIBRARY_PREFIX KittyHttp_
419 * #include "logging.h"
420 *
421 * Regardless of the method chosen, the end result is that bt_log symbols will
422 * be prefixed with "KittyHttp_", so if a user of KittyHttp (say DogeBrowser)
423 * also uses bt_log for logging, they will not interferer with each other. Both
424 * will have their own log level, output facility, format options etc.
425 */
426 #ifdef BT_LOG_LIBRARY_PREFIX
427 #define _BT_LOG_DECOR__(prefix, name) prefix ## name
428 #define _BT_LOG_DECOR_(prefix, name) _BT_LOG_DECOR__(prefix, name)
429 #define _BT_LOG_DECOR(name) _BT_LOG_DECOR_(BT_LOG_LIBRARY_PREFIX, name)
430
431 #define bt_log_set_tag_prefix _BT_LOG_DECOR(bt_log_set_tag_prefix)
432 #define bt_log_set_mem_width _BT_LOG_DECOR(bt_log_set_mem_width)
433 #define bt_log_set_output_level _BT_LOG_DECOR(bt_log_set_output_level)
434 #define bt_log_set_output_v _BT_LOG_DECOR(bt_log_set_output_v)
435 #define bt_log_set_output_p _BT_LOG_DECOR(bt_log_set_output_p)
436 #define bt_log_out_stderr_callback _BT_LOG_DECOR(bt_log_out_stderr_callback)
437 #define _bt_log_tag_prefix _BT_LOG_DECOR(_bt_log_tag_prefix)
438 #define _bt_log_global_format _BT_LOG_DECOR(_bt_log_global_format)
439 #define _bt_log_global_output _BT_LOG_DECOR(_bt_log_global_output)
440 #define _bt_log_global_output_lvl _BT_LOG_DECOR(_bt_log_global_output_lvl)
441 #define _bt_log_write_d _BT_LOG_DECOR(_bt_log_write_d)
442 #define _bt_log_write_aux_d _BT_LOG_DECOR(_bt_log_write_aux_d)
443 #define _bt_log_write _BT_LOG_DECOR(_bt_log_write)
444 #define _bt_log_write_aux _BT_LOG_DECOR(_bt_log_write_aux)
445 #define _bt_log_write_mem_d _BT_LOG_DECOR(_bt_log_write_mem_d)
446 #define _bt_log_write_mem_aux_d _BT_LOG_DECOR(_bt_log_write_mem_aux_d)
447 #define _bt_log_write_mem _BT_LOG_DECOR(_bt_log_write_mem)
448 #define _bt_log_write_mem_aux _BT_LOG_DECOR(_bt_log_write_mem_aux)
449 #define _bt_log_stderr_spec _BT_LOG_DECOR(_bt_log_stderr_spec)
450 #endif
451
452 #if defined(__printflike)
453 #define _BT_LOG_PRINTFLIKE(str_index, first_to_check) \
454 __printflike(str_index, first_to_check)
455 #elif defined(__MINGW_PRINTF_FORMAT)
456 #define _BT_LOG_PRINTFLIKE(str_index, first_to_check) \
457 __attribute__((format(__MINGW_PRINTF_FORMAT, str_index, first_to_check)))
458 #elif defined(__GNUC__)
459 #define _BT_LOG_PRINTFLIKE(str_index, first_to_check) \
460 __attribute__((format(__printf__, str_index, first_to_check)))
461 #else
462 #define _BT_LOG_PRINTFLIKE(str_index, first_to_check)
463 #endif
464
465 #if (defined(_WIN32) || defined(_WIN64)) && !defined(__GNUC__)
466 #define _BT_LOG_FUNCTION __FUNCTION__
467 #else
468 #define _BT_LOG_FUNCTION __func__
469 #endif
470
471 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
472 #define _BT_LOG_INLINE __inline
473 #define _BT_LOG_IF(cond) \
474 __pragma(warning(push)) \
475 __pragma(warning(disable:4127)) \
476 if(cond) \
477 __pragma(warning(pop))
478 #define _BT_LOG_WHILE(cond) \
479 __pragma(warning(push)) \
480 __pragma(warning(disable:4127)) \
481 while(cond) \
482 __pragma(warning(pop))
483 #else
484 #define _BT_LOG_INLINE inline
485 #define _BT_LOG_IF(cond) if(cond)
486 #define _BT_LOG_WHILE(cond) while(cond)
487 #endif
488 #define _BT_LOG_NEVER _BT_LOG_IF(0)
489 #define _BT_LOG_ONCE _BT_LOG_WHILE(0)
490
491 #ifdef __cplusplus
492 extern "C" {
493 #endif
494
495 /* Set tag prefix. Prefix will be separated from the tag with dot ('.').
496 * Use 0 or empty string to disable (default). Common use is to set it to
497 * the process (or build target) name (e.g. to separate client and server
498 * processes). Function will NOT copy provided prefix string, but will store the
499 * pointer. Hence specified prefix string must remain valid. See
500 * BT_LOG_DEFINE_TAG_PREFIX for a way to set it before entering main() function.
501 * See BT_LOG_TAG for more information about tag and tag prefix.
502 */
503 void bt_log_set_tag_prefix(const char *const prefix);
504
505 /* Set number of bytes per log line in memory (ASCII-HEX) output. Example:
506 *
507 * I hello.MAIN 4c6f72656d20697073756d20646f6c6f Lorem ipsum dolo
508 * |<- w bytes ->| |<- w chars ->|
509 *
510 * See BT_LOGF_MEM and BT_LOGF_MEM_AUX for more details.
511 */
512 void bt_log_set_mem_width(const unsigned w);
513
514 /* Set "output" log level. See BT_MINIMAL_LOG_LEVEL and BT_LOG_OUTPUT_LEVEL for more
515 * info about log levels.
516 */
517 void bt_log_set_output_level(const int lvl);
518
519 /* Put mask is a set of flags that define what fields will be added to each
520 * log message. Default value is BT_LOG_PUT_STD and other flags could be used to
521 * alter its behavior. See bt_log_set_output_v() for more details.
522 *
523 * Note about BT_LOG_PUT_SRC: it will be added only in debug builds
524 * (BT_DEBUG_MODE is defined).
525 */
526 enum
527 {
528 BT_LOG_PUT_CTX = 1 << 0, /* context (time, pid, tid, log level) */
529 BT_LOG_PUT_TAG = 1 << 1, /* tag (including tag prefix) */
530 BT_LOG_PUT_SRC = 1 << 2, /* source location (file, line, function) */
531 BT_LOG_PUT_MSG = 1 << 3, /* message text (formatted string) */
532 BT_LOG_PUT_STD = 0xffff, /* everything (default) */
533 };
534
535 typedef struct bt_log_message
536 {
537 int lvl; /* Log level of the message */
538 const char *tag; /* Associated tag (without tag prefix) */
539 char *buf; /* Buffer start */
540 char *e; /* Buffer end (last position where EOL with 0 could be written) */
541 char *p; /* Buffer content end (append position) */
542 char *tag_b; /* Prefixed tag start */
543 char *tag_e; /* Prefixed tag end (if != tag_b, points to msg separator) */
544 char *msg_b; /* Message start (expanded format string) */
545 }
546 bt_log_message;
547
548 /* Type of output callback function. It will be called for each log line allowed
549 * by both "current" and "output" log levels ("enabled" and "turned on").
550 * Callback function is allowed to modify content of the buffers pointed by the
551 * msg, but it's not allowed to modify any of msg fields. Buffer pointed by msg
552 * is UTF-8 encoded (no BOM mark).
553 */
554 typedef void (*bt_log_output_cb)(const bt_log_message *msg, void *arg);
555
556 /* Format options. For more details see bt_log_set_mem_width().
557 */
558 typedef struct bt_log_format
559 {
560 unsigned mem_width; /* Bytes per line in memory (ASCII-HEX) dump */
561 }
562 bt_log_format;
563
564 /* Output facility.
565 */
566 typedef struct bt_log_output
567 {
568 unsigned mask; /* What to put into log line buffer (see BT_LOG_PUT_XXX) */
569 void *arg; /* User provided output callback argument */
570 bt_log_output_cb callback; /* Output callback function */
571 }
572 bt_log_output;
573
574 /* Set output callback function.
575 *
576 * Mask allows to control what information will be added to the log line buffer
577 * before callback function is invoked. Default mask value is BT_LOG_PUT_STD.
578 */
579 void bt_log_set_output_v(const unsigned mask, void *const arg,
580 const bt_log_output_cb callback);
581 static _BT_LOG_INLINE void bt_log_set_output_p(const bt_log_output *const output)
582 {
583 bt_log_set_output_v(output->mask, output->arg, output->callback);
584 }
585
586 /* Used with _AUX macros and allows to override global format and output
587 * facility. Use BT_LOG_GLOBAL_FORMAT and BT_LOG_GLOBAL_OUTPUT for values from
588 * global configuration. Example:
589 *
590 * static const bt_log_output module_output = {
591 * BT_LOG_PUT_STD, 0, custom_output_callback
592 * };
593 * static const bt_log_spec module_spec = {
594 * BT_LOG_GLOBAL_FORMAT, &module_output
595 * };
596 * BT_LOGI_AUX(&module_spec, "Position: %ix%i", x, y);
597 *
598 * See BT_LOGF_AUX and BT_LOGF_MEM_AUX for details.
599 */
600 typedef struct bt_log_spec
601 {
602 const bt_log_format *format;
603 const bt_log_output *output;
604 }
605 bt_log_spec;
606
607 #ifdef __cplusplus
608 }
609 #endif
610
611 /* Execute log statement if condition is true. Example:
612 *
613 * BT_LOG_IF(1 < 2, BT_LOGI("Log this"));
614 * BT_LOG_IF(1 > 2, BT_LOGI("Don't log this"));
615 *
616 * Keep in mind though, that if condition can't be evaluated at compile time,
617 * then it will be evaluated at run time. This will increase exectuable size
618 * and can have noticeable performance overhead. Try to limit conditions to
619 * expressions that can be evaluated at compile time.
620 */
621 #define BT_LOG_IF(cond, f) do { _BT_LOG_IF((cond)) { f; } } _BT_LOG_ONCE
622
623 /* Mark log statement as "secret". Log statements that are marked as secrets
624 * will NOT be executed when censoring is enabled (see BT_LOG_CENSORED).
625 * Example:
626 *
627 * BT_LOG_SECRET(BT_LOGI("Credit card: %s", credit_card));
628 * BT_LOG_SECRET(BT_LOGD_MEM(cipher, cipher_sz, "Cipher bytes:"));
629 */
630 #define BT_LOG_SECRET(f) BT_LOG_IF(BT_LOG_SECRETS, f)
631
632 /* Check "current" log level at compile time (ignoring "output" log level).
633 * Evaluates to true when specified log level is enabled. For example:
634 *
635 * #if BT_LOG_ENABLED_DEBUG
636 * const char *const g_enum_strings[] = {
637 * "enum_value_0", "enum_value_1", "enum_value_2"
638 * };
639 * #endif
640 * // ...
641 * #if BT_LOG_ENABLED_DEBUG
642 * BT_LOGD("enum value: %s", g_enum_strings[v]);
643 * #endif
644 *
645 * See BT_MINIMAL_LOG_LEVEL for details.
646 */
647 #define BT_LOG_ENABLED(lvl) ((lvl) >= _BT_MINIMAL_LOG_LEVEL)
648 #define BT_LOG_ENABLED_TRACE BT_LOG_ENABLED(BT_LOG_TRACE)
649 #define BT_LOG_ENABLED_DEBUG BT_LOG_ENABLED(BT_LOG_DEBUG)
650 #define BT_LOG_ENABLED_INFO BT_LOG_ENABLED(BT_LOG_INFO)
651 #define BT_LOG_ENABLED_WARN BT_LOG_ENABLED(BT_LOG_WARN)
652 #define BT_LOG_ENABLED_ERROR BT_LOG_ENABLED(BT_LOG_ERROR)
653 #define BT_LOG_ENABLED_FATAL BT_LOG_ENABLED(BT_LOG_FATAL)
654
655 /* Check "output" log level at run time (taking into account "current" log
656 * level as well). Evaluates to true when specified log level is turned on AND
657 * enabled. For example:
658 *
659 * if (BT_LOG_ON_DEBUG)
660 * {
661 * char hash[65];
662 * sha256(data_ptr, data_sz, hash);
663 * BT_LOGD("data: len=%u, sha256=%s", data_sz, hash);
664 * }
665 *
666 * See BT_LOG_OUTPUT_LEVEL for details.
667 */
668 #define BT_LOG_ON_CUR_LVL(lvl, cur_lvl) \
669 (BT_LOG_ENABLED((lvl)) && (lvl) >= (cur_lvl))
670 #define BT_LOG_ON(lvl) \
671 (BT_LOG_ENABLED((lvl)) && (lvl) >= _BT_LOG_OUTPUT_LEVEL)
672 #define BT_LOG_ON_TRACE BT_LOG_ON(BT_LOG_TRACE)
673 #define BT_LOG_ON_DEBUG BT_LOG_ON(BT_LOG_DEBUG)
674 #define BT_LOG_ON_INFO BT_LOG_ON(BT_LOG_INFO)
675 #define BT_LOG_ON_WARN BT_LOG_ON(BT_LOG_WARN)
676 #define BT_LOG_ON_ERROR BT_LOG_ON(BT_LOG_ERROR)
677 #define BT_LOG_ON_FATAL BT_LOG_ON(BT_LOG_FATAL)
678
679 #ifdef __cplusplus
680 extern "C" {
681 #endif
682
683 extern const char *_bt_log_tag_prefix;
684 extern bt_log_format _bt_log_global_format;
685 extern bt_log_output _bt_log_global_output;
686 extern int _bt_log_global_output_lvl;
687 extern const bt_log_spec _bt_log_stderr_spec;
688
689 BT_HIDDEN
690 void _bt_log_write_d(
691 const char *const func, const char *const file, const unsigned line,
692 const int lvl, const char *const tag,
693 const char *const fmt, ...) _BT_LOG_PRINTFLIKE(6, 7);
694
695 BT_HIDDEN
696 void _bt_log_write_aux_d(
697 const char *const func, const char *const file, const unsigned line,
698 const bt_log_spec *const log, const int lvl, const char *const tag,
699 const char *const fmt, ...) _BT_LOG_PRINTFLIKE(7, 8);
700
701 BT_HIDDEN
702 void _bt_log_write(
703 const int lvl, const char *const tag,
704 const char *const fmt, ...) _BT_LOG_PRINTFLIKE(3, 4);
705
706 BT_HIDDEN
707 void _bt_log_write_aux(
708 const bt_log_spec *const log, const int lvl, const char *const tag,
709 const char *const fmt, ...) _BT_LOG_PRINTFLIKE(4, 5);
710
711 BT_HIDDEN
712 void _bt_log_write_mem_d(
713 const char *const func, const char *const file, const unsigned line,
714 const int lvl, const char *const tag,
715 const void *const d, const unsigned d_sz,
716 const char *const fmt, ...) _BT_LOG_PRINTFLIKE(8, 9);
717
718 BT_HIDDEN
719 void _bt_log_write_mem_aux_d(
720 const char *const func, const char *const file, const unsigned line,
721 const bt_log_spec *const log, const int lvl, const char *const tag,
722 const void *const d, const unsigned d_sz,
723 const char *const fmt, ...) _BT_LOG_PRINTFLIKE(9, 10);
724
725 BT_HIDDEN
726 void _bt_log_write_mem(
727 const int lvl, const char *const tag,
728 const void *const d, const unsigned d_sz,
729 const char *const fmt, ...) _BT_LOG_PRINTFLIKE(5, 6);
730
731 BT_HIDDEN
732 void _bt_log_write_mem_aux(
733 const bt_log_spec *const log, const int lvl, const char *const tag,
734 const void *const d, const unsigned d_sz,
735 const char *const fmt, ...) _BT_LOG_PRINTFLIKE(6, 7);
736
737 #ifdef __cplusplus
738 }
739 #endif
740
741 /* Message logging macros:
742 * - BT_LOGT("format string", args, ...)
743 * - BT_LOGD("format string", args, ...)
744 * - BT_LOGI("format string", args, ...)
745 * - BT_LOGW("format string", args, ...)
746 * - BT_LOGE("format string", args, ...)
747 * - BT_LOGF("format string", args, ...)
748 *
749 * Message and error string (errno) logging macros:
750 * - BT_LOGT_ERRNO("initial message", "format string", args, ...)
751 * - BT_LOGD_ERRNO("initial message", "format string", args, ...)
752 * - BT_LOGI_ERRNO("initial message", "format string", args, ...)
753 * - BT_LOGW_ERRNO("initial message", "format string", args, ...)
754 * - BT_LOGE_ERRNO("initial message", "format string", args, ...)
755 * - BT_LOGF_ERRNO("initial message", "format string", args, ...)
756 *
757 * Memory logging macros:
758 * - BT_LOGT_MEM(data_ptr, data_sz, "format string", args, ...)
759 * - BT_LOGD_MEM(data_ptr, data_sz, "format string", args, ...)
760 * - BT_LOGI_MEM(data_ptr, data_sz, "format string", args, ...)
761 * - BT_LOGW_MEM(data_ptr, data_sz, "format string", args, ...)
762 * - BT_LOGE_MEM(data_ptr, data_sz, "format string", args, ...)
763 * - BT_LOGF_MEM(data_ptr, data_sz, "format string", args, ...)
764 *
765 * Auxiliary logging macros:
766 * - BT_LOGT_AUX(&log_instance, "format string", args, ...)
767 * - BT_LOGD_AUX(&log_instance, "format string", args, ...)
768 * - BT_LOGI_AUX(&log_instance, "format string", args, ...)
769 * - BT_LOGW_AUX(&log_instance, "format string", args, ...)
770 * - BT_LOGE_AUX(&log_instance, "format string", args, ...)
771 * - BT_LOGF_AUX(&log_instance, "format string", args, ...)
772 *
773 * Auxiliary memory logging macros:
774 * - BT_LOGT_MEM_AUX(&log_instance, data_ptr, data_sz, "format string", args, ...)
775 * - BT_LOGD_MEM_AUX(&log_instance, data_ptr, data_sz, "format string", args, ...)
776 * - BT_LOGI_MEM_AUX(&log_instance, data_ptr, data_sz, "format string", args, ...)
777 * - BT_LOGW_MEM_AUX(&log_instance, data_ptr, data_sz, "format string", args, ...)
778 * - BT_LOGE_MEM_AUX(&log_instance, data_ptr, data_sz, "format string", args, ...)
779 * - BT_LOGF_MEM_AUX(&log_instance, data_ptr, data_sz, "format string", args, ...)
780 *
781 * Preformatted string logging macros:
782 * - BT_LOGT_STR("preformatted string");
783 * - BT_LOGD_STR("preformatted string");
784 * - BT_LOGI_STR("preformatted string");
785 * - BT_LOGW_STR("preformatted string");
786 * - BT_LOGE_STR("preformatted string");
787 * - BT_LOGF_STR("preformatted string");
788 *
789 * Explicit log level and tag macros:
790 * - BT_LOG_WRITE(level, tag, "format string", args, ...)
791 * - BT_LOG_WRITE_MEM(level, tag, data_ptr, data_sz, "format string", args, ...)
792 * - BT_LOG_WRITE_AUX(&log_instance, level, tag, "format string", args, ...)
793 * - BT_LOG_WRITE_MEM_AUX(&log_instance, level, tag, data_ptr, data_sz,
794 * "format string", args, ...)
795 *
796 * Explicit log level, current log level, and tag:
797 * - BT_LOG_WRITE_CUR_LVL(level, cur_level, tag, "format string", args, ...)
798 *
799 * Format string follows printf() conventions. Both data_ptr and data_sz could
800 * be 0. Tag can be 0 as well. Most compilers will verify that type of arguments
801 * match format specifiers in format string.
802 *
803 * Library assuming UTF-8 encoding for all strings (char *), including format
804 * string itself.
805 */
806 #if BT_LOG_SRCLOC_NONE == _BT_LOG_SRCLOC
807 #define BT_LOG_WRITE(lvl, tag, ...) \
808 do { \
809 if (BT_LOG_ON(lvl)) \
810 _bt_log_write(lvl, tag, __VA_ARGS__); \
811 } _BT_LOG_ONCE
812 #define BT_LOG_WRITE_CUR_LVL(lvl, cur_lvl, tag, ...) \
813 do { \
814 if (BT_LOG_ON_CUR_LVL((lvl), (cur_lvl))) \
815 _bt_log_write(lvl, tag, __VA_ARGS__); \
816 } _BT_LOG_ONCE
817 #define BT_LOG_WRITE_MEM(lvl, tag, d, d_sz, ...) \
818 do { \
819 if (BT_LOG_ON(lvl)) \
820 _bt_log_write_mem(lvl, tag, d, d_sz, __VA_ARGS__); \
821 } _BT_LOG_ONCE
822 #define BT_LOG_WRITE_AUX(log, lvl, tag, ...) \
823 do { \
824 if (BT_LOG_ON(lvl)) \
825 _bt_log_write_aux(log, lvl, tag, __VA_ARGS__); \
826 } _BT_LOG_ONCE
827 #define BT_LOG_WRITE_MEM_AUX(log, lvl, tag, d, d_sz, ...) \
828 do { \
829 if (BT_LOG_ON(lvl)) \
830 _bt_log_write_mem_aux(log, lvl, tag, d, d_sz, __VA_ARGS__); \
831 } _BT_LOG_ONCE
832 #else
833 #define BT_LOG_WRITE(lvl, tag, ...) \
834 do { \
835 if (BT_LOG_ON(lvl)) \
836 _bt_log_write_d(_BT_LOG_SRCLOC_FUNCTION, __FILE__, __LINE__, \
837 lvl, tag, __VA_ARGS__); \
838 } _BT_LOG_ONCE
839 #define BT_LOG_WRITE_CUR_LVL(lvl, cur_lvl, tag, ...) \
840 do { \
841 if (BT_LOG_ON_CUR_LVL((lvl), (cur_lvl))) \
842 _bt_log_write_d(_BT_LOG_SRCLOC_FUNCTION, __FILE__, __LINE__, \
843 lvl, tag, __VA_ARGS__); \
844 } _BT_LOG_ONCE
845 #define BT_LOG_WRITE_MEM(lvl, tag, d, d_sz, ...) \
846 do { \
847 if (BT_LOG_ON(lvl)) \
848 _bt_log_write_mem_d(_BT_LOG_SRCLOC_FUNCTION, __FILE__, __LINE__, \
849 lvl, tag, d, d_sz, __VA_ARGS__); \
850 } _BT_LOG_ONCE
851 #define BT_LOG_WRITE_AUX(log, lvl, tag, ...) \
852 do { \
853 if (BT_LOG_ON(lvl)) \
854 _bt_log_write_aux_d(_BT_LOG_SRCLOC_FUNCTION, __FILE__, __LINE__, \
855 log, lvl, tag, __VA_ARGS__); \
856 } _BT_LOG_ONCE
857 #define BT_LOG_WRITE_MEM_AUX(log, lvl, tag, d, d_sz, ...) \
858 do { \
859 if (BT_LOG_ON(lvl)) \
860 _bt_log_write_mem_aux_d(_BT_LOG_SRCLOC_FUNCTION, __FILE__, __LINE__, \
861 log, lvl, tag, d, d_sz, __VA_ARGS__); \
862 } _BT_LOG_ONCE
863 #endif
864
865 #define BT_LOG_WRITE_ERRNO_CUR_LVL(lvl, cur_lvl, tag, _msg, _fmt, args...) \
866 do { \
867 const char *error_str; \
868 error_str = g_strerror(errno); \
869 BT_LOG_WRITE_CUR_LVL(lvl, cur_lvl, tag, _msg ": %s" _fmt, error_str, ## args); \
870 } _BT_LOG_ONCE
871
872 #define BT_LOG_WRITE_ERRNO(lvl, tag, _msg, _fmt, args...) \
873 do { \
874 BT_LOG_WRITE_ERRNO_CUR_LVL(lvl, _BT_LOG_OUTPUT_LEVEL, tag, _msg, _fmt, ## args); \
875 } _BT_LOG_ONCE
876
877 static _BT_LOG_INLINE void _bt_log_unused(const int dummy, ...) {(void)dummy;}
878
879 #define _BT_LOG_UNUSED(...) \
880 do { _BT_LOG_NEVER _bt_log_unused(0, __VA_ARGS__); } _BT_LOG_ONCE
881
882 #if BT_LOG_ENABLED_TRACE
883 #define BT_LOGT(...) \
884 BT_LOG_WRITE(BT_LOG_TRACE, _BT_LOG_TAG, __VA_ARGS__)
885 #define BT_LOGT_ERRNO(...) \
886 BT_LOG_WRITE_ERRNO(BT_LOG_TRACE, _BT_LOG_TAG, __VA_ARGS__)
887 #define BT_LOGT_AUX(log, ...) \
888 BT_LOG_WRITE_AUX(log, BT_LOG_TRACE, _BT_LOG_TAG, __VA_ARGS__)
889 #define BT_LOGT_MEM(d, d_sz, ...) \
890 BT_LOG_WRITE_MEM(BT_LOG_TRACE, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
891 #define BT_LOGT_MEM_AUX(log, d, d_sz, ...) \
892 BT_LOG_WRITE_MEM(log, BT_LOG_TRACE, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
893 #else
894 #define BT_LOGT(...) _BT_LOG_UNUSED(__VA_ARGS__)
895 #define BT_LOGT_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
896 #define BT_LOGT_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
897 #define BT_LOGT_MEM_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
898 #endif
899
900 #if BT_LOG_ENABLED_DEBUG
901 #define BT_LOGD(...) \
902 BT_LOG_WRITE(BT_LOG_DEBUG, _BT_LOG_TAG, __VA_ARGS__)
903 #define BT_LOGD_ERRNO(...) \
904 BT_LOG_WRITE_ERRNO(BT_LOG_DEBUG, _BT_LOG_TAG, __VA_ARGS__)
905 #define BT_LOGD_AUX(log, ...) \
906 BT_LOG_WRITE_AUX(log, BT_LOG_DEBUG, _BT_LOG_TAG, __VA_ARGS__)
907 #define BT_LOGD_MEM(d, d_sz, ...) \
908 BT_LOG_WRITE_MEM(BT_LOG_DEBUG, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
909 #define BT_LOGD_MEM_AUX(log, d, d_sz, ...) \
910 BT_LOG_WRITE_MEM_AUX(log, BT_LOG_DEBUG, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
911 #else
912 #define BT_LOGD(...) _BT_LOG_UNUSED(__VA_ARGS__)
913 #define BT_LOGD_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
914 #define BT_LOGD_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
915 #define BT_LOGD_MEM_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
916 #endif
917
918 #if BT_LOG_ENABLED_INFO
919 #define BT_LOGI(...) \
920 BT_LOG_WRITE(BT_LOG_INFO, _BT_LOG_TAG, __VA_ARGS__)
921 #define BT_LOGI_ERRNO(...) \
922 BT_LOG_WRITE_ERRNO(BT_LOG_INFO, _BT_LOG_TAG, __VA_ARGS__)
923 #define BT_LOGI_AUX(log, ...) \
924 BT_LOG_WRITE_AUX(log, BT_LOG_INFO, _BT_LOG_TAG, __VA_ARGS__)
925 #define BT_LOGI_MEM(d, d_sz, ...) \
926 BT_LOG_WRITE_MEM(BT_LOG_INFO, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
927 #define BT_LOGI_MEM_AUX(log, d, d_sz, ...) \
928 BT_LOG_WRITE_MEM_AUX(log, BT_LOG_INFO, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
929 #else
930 #define BT_LOGI(...) _BT_LOG_UNUSED(__VA_ARGS__)
931 #define BT_LOGI_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
932 #define BT_LOGI_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
933 #define BT_LOGI_MEM_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
934 #endif
935
936 #if BT_LOG_ENABLED_WARN
937 #define BT_LOGW(...) \
938 BT_LOG_WRITE(BT_LOG_WARN, _BT_LOG_TAG, __VA_ARGS__)
939 #define BT_LOGW_ERRNO(...) \
940 BT_LOG_WRITE_ERRNO(BT_LOG_WARN, _BT_LOG_TAG, __VA_ARGS__)
941 #define BT_LOGW_AUX(log, ...) \
942 BT_LOG_WRITE_AUX(log, BT_LOG_WARN, _BT_LOG_TAG, __VA_ARGS__)
943 #define BT_LOGW_MEM(d, d_sz, ...) \
944 BT_LOG_WRITE_MEM(BT_LOG_WARN, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
945 #define BT_LOGW_MEM_AUX(log, d, d_sz, ...) \
946 BT_LOG_WRITE_MEM_AUX(log, BT_LOG_WARN, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
947 #else
948 #define BT_LOGW(...) _BT_LOG_UNUSED(__VA_ARGS__)
949 #define BT_LOGW_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
950 #define BT_LOGW_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
951 #define BT_LOGW_MEM_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
952 #endif
953
954 #if BT_LOG_ENABLED_ERROR
955 #define BT_LOGE(...) \
956 BT_LOG_WRITE(BT_LOG_ERROR, _BT_LOG_TAG, __VA_ARGS__)
957 #define BT_LOGE_ERRNO(...) \
958 BT_LOG_WRITE_ERRNO(BT_LOG_ERROR, _BT_LOG_TAG, __VA_ARGS__)
959 #define BT_LOGE_AUX(log, ...) \
960 BT_LOG_WRITE_AUX(log, BT_LOG_ERROR, _BT_LOG_TAG, __VA_ARGS__)
961 #define BT_LOGE_MEM(d, d_sz, ...) \
962 BT_LOG_WRITE_MEM(BT_LOG_ERROR, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
963 #define BT_LOGE_MEM_AUX(log, d, d_sz, ...) \
964 BT_LOG_WRITE_MEM_AUX(log, BT_LOG_ERROR, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
965 #else
966 #define BT_LOGE(...) _BT_LOG_UNUSED(__VA_ARGS__)
967 #define BT_LOGE_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
968 #define BT_LOGE_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
969 #define BT_LOGE_MEM_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
970 #endif
971
972 #if BT_LOG_ENABLED_FATAL
973 #define BT_LOGF(...) \
974 BT_LOG_WRITE(BT_LOG_FATAL, _BT_LOG_TAG, __VA_ARGS__)
975 #define BT_LOGF_ERRNO(...) \
976 BT_LOG_WRITE_ERRNO(BT_LOG_FATAL, _BT_LOG_TAG, __VA_ARGS__)
977 #define BT_LOGF_AUX(log, ...) \
978 BT_LOG_WRITE_AUX(log, BT_LOG_FATAL, _BT_LOG_TAG, __VA_ARGS__)
979 #define BT_LOGF_MEM(d, d_sz, ...) \
980 BT_LOG_WRITE_MEM(BT_LOG_FATAL, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
981 #define BT_LOGF_MEM_AUX(log, d, d_sz, ...) \
982 BT_LOG_WRITE_MEM_AUX(log, BT_LOG_FATAL, _BT_LOG_TAG, d, d_sz, __VA_ARGS__)
983 #else
984 #define BT_LOGF(...) _BT_LOG_UNUSED(__VA_ARGS__)
985 #define BT_LOGF_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
986 #define BT_LOGF_MEM(...) _BT_LOG_UNUSED(__VA_ARGS__)
987 #define BT_LOGF_MEM_AUX(...) _BT_LOG_UNUSED(__VA_ARGS__)
988 #endif
989
990 #define BT_LOGT_STR(s) BT_LOGT("%s", (s))
991 #define BT_LOGD_STR(s) BT_LOGD("%s", (s))
992 #define BT_LOGI_STR(s) BT_LOGI("%s", (s))
993 #define BT_LOGW_STR(s) BT_LOGW("%s", (s))
994 #define BT_LOGE_STR(s) BT_LOGE("%s", (s))
995 #define BT_LOGF_STR(s) BT_LOGF("%s", (s))
996
997 #ifdef __cplusplus
998 extern "C" {
999 #endif
1000
1001 /* Output to standard error stream. Library uses it by default, though in few
1002 * cases it could be necessary to specify it explicitly. For example, when
1003 * bt_log library is compiled with BT_LOG_EXTERN_GLOBAL_OUTPUT, application must
1004 * define and initialize global output variable:
1005 *
1006 * BT_LOG_DEFINE_GLOBAL_OUTPUT = {BT_LOG_OUT_STDERR};
1007 *
1008 * Another example is when using custom output, stderr could be used as a
1009 * fallback when custom output facility failed to initialize:
1010 *
1011 * bt_log_set_output_v(BT_LOG_OUT_STDERR);
1012 */
1013 enum { BT_LOG_OUT_STDERR_MASK = BT_LOG_PUT_STD };
1014
1015 BT_HIDDEN
1016 void bt_log_out_stderr_callback(const bt_log_message *const msg, void *arg);
1017 #define BT_LOG_OUT_STDERR BT_LOG_OUT_STDERR_MASK, 0, bt_log_out_stderr_callback
1018
1019 /* Predefined spec for stderr. Uses global format options (BT_LOG_GLOBAL_FORMAT)
1020 * and BT_LOG_OUT_STDERR. Could be used to force output to stderr for a
1021 * particular message. Example:
1022 *
1023 * f = fopen("foo.log", "w");
1024 * if (!f)
1025 * BT_LOGE_AUX(BT_LOG_STDERR, "Failed to open log file");
1026 */
1027 #define BT_LOG_STDERR (&_bt_log_stderr_spec)
1028
1029 /*
1030 * Returns the equivalent letter of the log level `level`.
1031 *
1032 * `level` must be a valid log level.
1033 */
1034 static inline
1035 char bt_log_get_letter_from_level(int level)
1036 {
1037 char letter;
1038
1039 switch (level) {
1040 case BT_LOG_TRACE:
1041 letter = 'T';
1042 break;
1043 case BT_LOG_DEBUG:
1044 letter = 'D';
1045 break;
1046 case BT_LOG_INFO:
1047 letter = 'I';
1048 break;
1049 case BT_LOG_WARN:
1050 letter = 'W';
1051 break;
1052 case BT_LOG_ERROR:
1053 letter = 'E';
1054 break;
1055 case BT_LOG_FATAL:
1056 letter = 'F';
1057 break;
1058 case BT_LOG_NONE:
1059 letter = 'N';
1060 break;
1061 default:
1062 abort();
1063 }
1064
1065 return letter;
1066 }
1067
1068 /*
1069 * Returns the log level for the string `str`, or -1 if `str` is not a
1070 * valid log level string.
1071 */
1072 static inline
1073 int bt_log_get_level_from_string(const char *str)
1074 {
1075 int level = -1;
1076
1077 BT_ASSERT(str);
1078
1079 if (strcmp(str, "TRACE") == 0 ||
1080 strcmp(str, "T") == 0) {
1081 level = BT_LOG_TRACE;
1082 } else if (strcmp(str, "DEBUG") == 0 ||
1083 strcmp(str, "D") == 0) {
1084 level = BT_LOG_DEBUG;
1085 } else if (strcmp(str, "INFO") == 0 ||
1086 strcmp(str, "I") == 0) {
1087 level = BT_LOG_INFO;
1088 } else if (strcmp(str, "WARN") == 0 ||
1089 strcmp(str, "WARNING") == 0 ||
1090 strcmp(str, "W") == 0) {
1091 level = BT_LOG_WARN;
1092 } else if (strcmp(str, "ERROR") == 0 ||
1093 strcmp(str, "E") == 0) {
1094 level = BT_LOG_ERROR;
1095 } else if (strcmp(str, "FATAL") == 0 ||
1096 strcmp(str, "F") == 0) {
1097 level = BT_LOG_FATAL;
1098 } else if (strcmp(str, "NONE") == 0 ||
1099 strcmp(str, "N") == 0) {
1100 level = BT_LOG_NONE;
1101 } else {
1102 /* FIXME: Should we warn here? How? */
1103 }
1104
1105 return level;
1106 }
1107
1108 /*
1109 * Returns the log level for the letter `letter`, or -1 if `letter` is
1110 * not a valid log level string.
1111 */
1112 static inline
1113 int bt_log_get_level_from_letter(char letter)
1114 {
1115 char str[] = {letter, '\0'};
1116
1117 return bt_log_get_level_from_string(str);
1118 }
1119
1120 static inline
1121 int bt_log_get_level_from_env(const char *var)
1122 {
1123 const char *varval = getenv(var);
1124 int level = BT_LOG_NONE;
1125
1126 if (!varval) {
1127 goto end;
1128 }
1129
1130 level = bt_log_get_level_from_string(varval);
1131 if (level < 0) {
1132 /* FIXME: Should we warn here? How? */
1133 level = BT_LOG_NONE;
1134 }
1135
1136 end:
1137 return level;
1138 }
1139
1140 #define BT_LOG_LEVEL_EXTERN_SYMBOL(_level_sym) \
1141 extern int _level_sym
1142
1143 #define BT_LOG_INIT_LOG_LEVEL(_level_sym, _env_var) \
1144 BT_HIDDEN int _level_sym = BT_LOG_NONE; \
1145 static \
1146 void __attribute__((constructor)) _bt_log_level_ctor(void) \
1147 { \
1148 _level_sym = bt_log_get_level_from_env(_env_var); \
1149 }
1150
1151 #define BT_LOG_SUPPORTED
1152
1153 #ifdef __cplusplus
1154 }
1155 #endif
1156
1157 #endif /* BABELTRACE_LOGGING_INTERNAL_H */
This page took 0.081867 seconds and 4 git commands to generate.