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