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