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