aboutsummaryrefslogtreecommitdiff
path: root/src/any_log.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/any_log.h')
-rw-r--r--src/any_log.h151
1 files changed, 91 insertions, 60 deletions
diff --git a/src/any_log.h b/src/any_log.h
index 4d4dc17..bccb8bb 100644
--- a/src/any_log.h
+++ b/src/any_log.h
@@ -1,4 +1,4 @@
-// any_log v0.3.1
+// any_log v0.3.2
//
// A single-file library that provides a simple and somewhat opinionated
// interface for logging and structured logging.
@@ -52,6 +52,19 @@ typedef enum {
ANY_LOG_ALL,
} any_log_level_t;
+// The value of ANY_LOG_CONTEXT should be used to pass some
+// extra information or context to the logging functions.
+// By default it is empty.
+//
+// Before including the header simply define your custom ANY_LOG_CONTEXT.
+//
+// #define ANY_LOG_CONTEXT get_thread_name()
+// #include "any_log.h"
+//
+#ifndef ANY_LOG_CONTEXT
+#define ANY_LOG_CONTEXT ""
+#endif
+
// The value of ANY_LOG_MODULE is used to indicate the current module.
// By default it is defined as __FILE__, which should expand to the
// source file path (relative to the compiler cwd).
@@ -62,19 +75,25 @@ typedef enum {
// #define ANY_LOG_MODULE "my-library"
// #include "any_log.h"
//
+// If you want to also include the current line, you could do something
+// like the following:
+//
+// #define STR2(x) #x
+// #define STR(x) STR2(x)
+// #define ANY_LOG_MODULE __FILE__ ":" STR(__LINE__)
+// #include "any_log.h"
+//
#ifndef ANY_LOG_MODULE
#define ANY_LOG_MODULE __FILE__
#endif
-// C99 and later define the __func__ variable
+// C99 and later defines the __func__ variable to hold the name of
+// the current function.
+//
#ifndef ANY_LOG_FUNC
#define ANY_LOG_FUNC __func__
#endif
-#ifndef ANY_LOG_LINE
-#define ANY_LOG_LINE __LINE__
-#endif
-
// log_panic is implemented with the function any_log_panic, which takes
// some extra parameters compared with the other log levels. This way we can
// include as many information as possible for identifying fatal errors.
@@ -88,7 +107,7 @@ typedef enum {
// NOTE: log_panic will always terminate the program and should be used only
// for non recoverable situations! For normal errors just use log_error.
//
-#define log_panic(...) any_log_panic(__FILE__, ANY_LOG_LINE, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__)
+#define log_panic(...) any_log_panic(__FILE__, __LINE__, ANY_LOG_CONTEXT, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__)
// log_[level] provide normal printf style logging.
//
@@ -105,20 +124,20 @@ typedef enum {
// respectively. As this will work only if they are defined before every header
// include, it is recommended to define this from the compiler.
//
-#define log_error(...) any_log_format(ANY_LOG_ERROR, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__)
-#define log_warn(...) any_log_format(ANY_LOG_WARN, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__)
-#define log_info(...) any_log_format(ANY_LOG_INFO, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__)
+#define log_error(...) any_log_format(ANY_LOG_ERROR, ANY_LOG_CONTEXT, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__)
+#define log_warn(...) any_log_format(ANY_LOG_WARN, ANY_LOG_CONTEXT, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__)
+#define log_info(...) any_log_format(ANY_LOG_INFO, ANY_LOG_CONTEXT, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__)
#ifdef ANY_LOG_NO_DEBUG
#define log_debug(...)
#else
-#define log_debug(...) any_log_format(ANY_LOG_DEBUG, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__)
+#define log_debug(...) any_log_format(ANY_LOG_DEBUG, ANY_LOG_CONTEXT, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__)
#endif
#ifdef ANY_LOG_NO_TRACE
#define log_trace(...)
#else
-#define log_trace(...) any_log_format(ANY_LOG_TRACE, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__)
+#define log_trace(...) any_log_format(ANY_LOG_TRACE, ANY_LOG_CONTEXT, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__)
#endif
// log_value_[level] provide structured logging.
@@ -178,7 +197,7 @@ typedef enum {
// #define ANY_LOG_IMPLEMENT
// #define ANY_LOG_NO_GENERIC
//
-// #define ANY_LOG_VALUE_BEFORE(stream, level, module, func, message)
+// #define ANY_LOG_VALUE_BEFORE(stream, level, context, module, func, message)
// fprintf(stream, "{\"module\": \"%s\", \"function\": \"%s\", \"level\": \"%s\", \"message\": \"%s\", ",
// module, func, any_log_level_strings[level], message)
//
@@ -206,7 +225,7 @@ typedef enum {
// #define ANY_LOG_VALUE_STRING(stream, key, value)
// fprintf(stream, "\"%s \": \"%s\"", key, value)
//
-// #define ANY_LOG_VALUE_AFTER(stream, level, module, func, message)
+// #define ANY_LOG_VALUE_AFTER(stream, level, context, module, func, message)
// fprintf(stream, "}\n")
//
// #include "any_log.h"
@@ -214,21 +233,21 @@ typedef enum {
// As with log_trace and log_debug, log_value_trace and log_value_debug can be
// disabled by defining ANY_LOG_NO_TRACE and ANY_LOG_NO_DEBUG respectively.
//
-#define log_value_error(...) any_log_value(ANY_LOG_ERROR, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__, (char *)NULL)
-#define log_value_warn(...) any_log_value(ANY_LOG_WARN, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__, (char *)NULL)
-#define log_value_info(...) any_log_value(ANY_LOG_INFO, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__, (char *)NULL)
-#define log_value_debug(...) any_log_value(ANY_LOG_DEBUG, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__, (char *)NULL)
+#define log_value_error(...) any_log_value(ANY_LOG_ERROR, ANY_LOG_CONTEXT, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__, (char *)NULL)
+#define log_value_warn(...) any_log_value(ANY_LOG_WARN, ANY_LOG_CONTEXT, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__, (char *)NULL)
+#define log_value_info(...) any_log_value(ANY_LOG_INFO, ANY_LOG_CONTEXT, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__, (char *)NULL)
+#define log_value_debug(...) any_log_value(ANY_LOG_DEBUG, ANY_LOG_CONTEXT, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__, (char *)NULL)
#ifdef ANY_LOG_NO_DEBUG
#define log_value_debug(...)
#else
-#define log_value_debug(...) any_log_value(ANY_LOG_DEBUG, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__, (char *)NULL)
+#define log_value_debug(...) any_log_value(ANY_LOG_DEBUG, ANY_LOG_CONTEXT, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__, (char *)NULL)
#endif
#ifdef ANY_LOG_NO_TRACE
#define log_value_trace(...)
#else
-#define log_value_trace(...) any_log_value(ANY_LOG_TRACE, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__, (char *)NULL)
+#define log_value_trace(...) any_log_value(ANY_LOG_TRACE, ANY_LOG_CONTEXT, ANY_LOG_MODULE, ANY_LOG_FUNC, __VA_ARGS__, (char *)NULL)
#endif
#ifndef ANY_LOG_NO_GENERIC
@@ -359,6 +378,7 @@ typedef enum {
ANY_LOG_COLOR_INFO,
ANY_LOG_COLOR_DEBUG,
ANY_LOG_COLOR_TRACE,
+ ANY_LOG_COLOR_CONTEXT,
ANY_LOG_COLOR_MODULE,
ANY_LOG_COLOR_FUNC,
ANY_LOG_COLOR_RESET,
@@ -385,20 +405,20 @@ extern const char *any_log_colors_disabled[ANY_LOG_COLOR_ALL];
// NOTE: You should never call the functions below directly!
// See the above explanations on how to use logging.
-ANY_LOG_ATTRIBUTE(format(printf, 4, 5))
-ANY_LOG_ATTRIBUTE(nonnull(2, 3, 4))
-void any_log_format(any_log_level_t level, const char *module,
- const char *func, const char *format, ...);
+ANY_LOG_ATTRIBUTE(format(printf, 5, 6))
+ANY_LOG_ATTRIBUTE(nonnull(2, 3, 4, 5))
+void any_log_format(any_log_level_t level, const char *context,
+ const char *module, const char *func, const char *format, ...);
-ANY_LOG_ATTRIBUTE(nonnull(2, 3, 4))
-void any_log_value(any_log_level_t level, const char *module,
- const char *func, const char *message, ...);
+ANY_LOG_ATTRIBUTE(nonnull(2, 3, 4, 5))
+void any_log_value(any_log_level_t level, const char *context,
+ const char *module, const char *func, const char *message, ...);
ANY_LOG_NORETURN
-ANY_LOG_ATTRIBUTE(format(printf, 5, 6))
-ANY_LOG_ATTRIBUTE(nonnull(1, 3, 4, 5))
-void any_log_panic(const char *file, int line, const char *module,
- const char *func, const char *format, ...);
+ANY_LOG_ATTRIBUTE(format(printf, 6, 7))
+ANY_LOG_ATTRIBUTE(nonnull(1, 3, 4, 5, 6))
+void any_log_panic(const char *file, int line, const char *context,
+ const char *module, const char *func, const char *format, ...);
#endif
@@ -509,6 +529,9 @@ const char **any_log_colors = any_log_colors_enabled;
#ifndef ANY_LOG_COLOR_RESET_DEFAULT
#define ANY_LOG_COLOR_RESET_DEFAULT "\x1b[0m"
#endif
+#ifndef ANY_LOG_COLOR_CONTEXT_DEFAULT
+#define ANY_LOG_COLOR_CONTEXT_DEFAULT ""
+#endif
#ifndef ANY_LOG_COLOR_MODULE_DEFAULT
#define ANY_LOG_COLOR_MODULE_DEFAULT ""
#endif
@@ -516,20 +539,21 @@ const char **any_log_colors = any_log_colors_enabled;
#define ANY_LOG_COLOR_FUNC_DEFAULT "\x1b[1m"
#endif
-const char *any_log_colors_enabled[ANY_LOG_ALL + 3] = {
+const char *any_log_colors_enabled[ANY_LOG_COLOR_ALL] = {
ANY_LOG_COLOR_PANIC_DEFAULT,
ANY_LOG_COLOR_ERROR_DEFAULT,
ANY_LOG_COLOR_WARN_DEFAULT,
ANY_LOG_COLOR_INFO_DEFAULT,
ANY_LOG_COLOR_DEBUG_DEFAULT,
ANY_LOG_COLOR_TRACE_DEFAULT,
+ ANY_LOG_COLOR_CONTEXT_DEFAULT,
ANY_LOG_COLOR_MODULE_DEFAULT,
ANY_LOG_COLOR_FUNC_DEFAULT,
ANY_LOG_COLOR_RESET_DEFAULT,
};
const char *any_log_colors_disabled[ANY_LOG_COLOR_ALL] = {
- "", "", "", "", "", "", "", "", ""
+ "", "", "", "", "", "", "", "", "", "",
};
#else
@@ -542,8 +566,9 @@ const char *any_log_colors_disabled[ANY_LOG_COLOR_ALL] = {
// Format for any_log_format (used at the start)
#ifndef ANY_LOG_FORMAT_BEFORE
-#define ANY_LOG_FORMAT_BEFORE(stream, level, module, func) \
- fprintf(stream, "[%s%s%s %s%s%s] %s%s%s: ", \
+#define ANY_LOG_FORMAT_BEFORE(stream, level, context, module, func) \
+ fprintf(stream, "[%s%s%s%s%s%s%s %s%s%s] %s%s%s: ", \
+ ANY_LOG_COLOR_GET(ANY_LOG_COLOR_CONTEXT), context, ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), *context ? " " : "", \
ANY_LOG_COLOR_GET(ANY_LOG_COLOR_MODULE), module, ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), \
ANY_LOG_COLOR_GET(ANY_LOG_COLOR_FUNC), func, ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), \
ANY_LOG_COLOR_GET(level), any_log_level_strings[level], ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET))
@@ -551,12 +576,12 @@ const char *any_log_colors_disabled[ANY_LOG_COLOR_ALL] = {
// Format for any_log_format (used at the end)
#ifndef ANY_LOG_FORMAT_AFTER
-#define ANY_LOG_FORMAT_AFTER(stream, level, module, func) \
+#define ANY_LOG_FORMAT_AFTER(stream, level, context, module, func) \
fprintf(stream, "\n")
#endif
-void any_log_format(any_log_level_t level, const char *module,
- const char *func, const char *format, ...)
+void any_log_format(any_log_level_t level, const char *context,
+ const char *module, const char *func, const char *format, ...)
{
if (level > any_log_level)
return;
@@ -564,19 +589,21 @@ void any_log_format(any_log_level_t level, const char *module,
FILE *stream = any_log_streams[level];
ANY_LOG_FLOCK(stream);
- ANY_LOG_FORMAT_BEFORE(stream, level, module, func);
+ ANY_LOG_FORMAT_BEFORE(stream, level, context, module, func);
va_list args;
va_start(args, format);
vfprintf(stream, format, args);
va_end(args);
- ANY_LOG_FORMAT_AFTER(stream, level, module, func);
+ ANY_LOG_FORMAT_AFTER(stream, level, context, module, func);
ANY_LOG_FUNLOCK(stream);
// NOTE: Suppress compiler warning if the user customizes the format string
// and doesn't use these values in it
+
+ (void)context;
(void)module;
(void)func;
}
@@ -590,8 +617,9 @@ void any_log_format(any_log_level_t level, const char *module,
// Format for any_log_value (used at the start)
#ifndef ANY_LOG_VALUE_BEFORE
-#define ANY_LOG_VALUE_BEFORE(stream, level, module, func, message) \
- fprintf(stream, "[%s%s%s %s%s%s] %s%s%s: %s [", \
+#define ANY_LOG_VALUE_BEFORE(stream, level, context, module, func, message) \
+ fprintf(stream, "[%s%s%s%s%s%s%s %s%s%s] %s%s%s: %s [", \
+ ANY_LOG_COLOR_GET(ANY_LOG_COLOR_CONTEXT), context, ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), *context ? " " : "", \
ANY_LOG_COLOR_GET(ANY_LOG_COLOR_MODULE), module, ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), \
ANY_LOG_COLOR_GET(ANY_LOG_COLOR_FUNC), func, ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), \
ANY_LOG_COLOR_GET(level), any_log_level_strings[level], ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), message)
@@ -599,7 +627,7 @@ void any_log_format(any_log_level_t level, const char *module,
// Format for any_log_value (used at the end)
#ifndef ANY_LOG_VALUE_AFTER
-#define ANY_LOG_VALUE_AFTER(stream, level, module, func, message) \
+#define ANY_LOG_VALUE_AFTER(stream, level, context, module, func, message) \
fprintf(stream, "]\n")
#endif
@@ -676,8 +704,8 @@ void any_log_format(any_log_level_t level, const char *module,
// NOTE: This function should be called with at least one parameter after message.
// The log_value_[level] macros automatically add a NULL.
//
-void any_log_value(any_log_level_t level, const char *module,
- const char *func, const char *message, ...)
+void any_log_value(any_log_level_t level, const char *context,
+ const char *module, const char *func, const char *message, ...)
{
if (level > any_log_level)
return;
@@ -685,7 +713,7 @@ void any_log_value(any_log_level_t level, const char *module,
FILE *stream = any_log_streams[level];
ANY_LOG_FLOCK(stream);
- ANY_LOG_VALUE_BEFORE(stream, level, module, func, message);
+ ANY_LOG_VALUE_BEFORE(stream, level, context, module, func, message);
va_list args;
va_start(args, message);
@@ -765,9 +793,10 @@ tdefault:;
va_end(args);
- ANY_LOG_VALUE_AFTER(stream, level, module, func, message);
+ ANY_LOG_VALUE_AFTER(stream, level, context, module, func, message);
ANY_LOG_FUNLOCK(stream);
+ (void)context;
(void)module;
(void)func;
(void)message;
@@ -781,22 +810,23 @@ tdefault:;
// NOTE: This function should never return!
//
#ifndef ANY_LOG_EXIT
-#define ANY_LOG_EXIT(file, line, module, func) abort()
+#define ANY_LOG_EXIT(file, line, context, module, func) abort()
#endif
// Format for any_log_panic (used at the start)
#ifndef ANY_LOG_PANIC_BEFORE
-#define ANY_LOG_PANIC_BEFORE(stream, file, line, module, func) \
- fprintf(stream, "[%s%s%s %s%s%s] %s%s%s: ", \
+#define ANY_LOG_PANIC_BEFORE(stream, file, line, context, module, func) \
+ fprintf(stream, "[%s%s%s%s%s%s%s %s%s%s] %s%s%s: ", \
+ ANY_LOG_COLOR_GET(ANY_LOG_COLOR_CONTEXT), context, ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), *context ? " " : "", \
ANY_LOG_COLOR_GET(ANY_LOG_COLOR_MODULE), module, ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), \
ANY_LOG_COLOR_GET(ANY_LOG_COLOR_FUNC), func, ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), \
ANY_LOG_COLOR_GET(ANY_LOG_PANIC), any_log_level_strings[ANY_LOG_PANIC], ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET))
#endif
-// Format for any_log_panic (used at the start)
+// Format for any_log_panic (used at the end)
#ifndef ANY_LOG_PANIC_AFTER
-#define ANY_LOG_PANIC_AFTER(stream, file, line, module, func) \
- fprintf(stream, "\n%spanic was invoked from%s %s:%d (module %s%s%s)\n", \
+#define ANY_LOG_PANIC_AFTER(stream, file, line, context, module, func) \
+ fprintf(stream, "\n%spanic was invoked from%s %s:%d (%s%s%s)\n", \
ANY_LOG_COLOR_GET(ANY_LOG_PANIC), ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET), file, line, \
ANY_LOG_COLOR_GET(ANY_LOG_COLOR_MODULE), module, ANY_LOG_COLOR_GET(ANY_LOG_COLOR_RESET))
#endif
@@ -804,29 +834,30 @@ tdefault:;
// NOTE: This function *exceptionally* gets more location information
// because we want to be specific at least for fatal errors
//
-void any_log_panic(const char *file, int line, const char *module,
- const char *func, const char *format, ...)
+void any_log_panic(const char *file, int line, const char *context,
+ const char *module, const char *func, const char *format, ...)
{
FILE *stream = any_log_streams[ANY_LOG_PANIC];
ANY_LOG_FLOCK(stream);
- ANY_LOG_PANIC_BEFORE(stream, file, line, module, func);
+ ANY_LOG_PANIC_BEFORE(stream, file, line, context, module, func);
va_list args;
va_start(args, format);
vfprintf(stream, format, args);
va_end(args);
- ANY_LOG_PANIC_AFTER(stream, file, line, module, func);
+ ANY_LOG_PANIC_AFTER(stream, file, line, context, module, func);
ANY_LOG_FUNLOCK(stream);
- (void)module;
- (void)func;
(void)file;
(void)line;
+ (void)context;
+ (void)module;
+ (void)func;
- ANY_LOG_EXIT(file, line, module, func);
+ ANY_LOG_EXIT(file, line, context, module, func);
// In a way or another, this function shall not return
abort();