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