aboutsummaryrefslogtreecommitdiff
path: root/src/log.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/log.h')
-rw-r--r--src/log.h96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/log.h b/src/log.h
new file mode 100644
index 0000000..e40fe3c
--- /dev/null
+++ b/src/log.h
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: MPL-2.0
+// Copyright (c) 2018 Yuxuan Shui <[email protected]>
+
+#pragma once
+#include <assert.h>
+#include <stdio.h>
+
+#include "compiler.h"
+
+enum log_level {
+ LOG_LEVEL_INVALID = -1,
+ LOG_LEVEL_TRACE = 0,
+ LOG_LEVEL_DEBUG,
+ LOG_LEVEL_INFO,
+ LOG_LEVEL_WARN,
+ LOG_LEVEL_ERROR,
+ LOG_LEVEL_FATAL,
+};
+
+#define LOG_UNLIKELY(level, x, ...) \
+ do { \
+ if (unlikely(LOG_LEVEL_##level >= log_get_level_tls())) { \
+ log_printf(tls_logger, LOG_LEVEL_##level, __func__, x, ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+#define LOG(level, x, ...) \
+ do { \
+ if (LOG_LEVEL_##level >= log_get_level_tls()) { \
+ log_printf(tls_logger, LOG_LEVEL_##level, __func__, x, ##__VA_ARGS__); \
+ } \
+ } while (0)
+#define log_trace(x, ...) LOG_UNLIKELY(TRACE, x, ##__VA_ARGS__)
+#define log_debug(x, ...) LOG_UNLIKELY(DEBUG, x, ##__VA_ARGS__)
+#define log_info(x, ...) LOG(INFO, x, ##__VA_ARGS__)
+#define log_warn(x, ...) LOG(WARN, x, ##__VA_ARGS__)
+#define log_error(x, ...) LOG(ERROR, x, ##__VA_ARGS__)
+#define log_fatal(x, ...) LOG(FATAL, x, ##__VA_ARGS__)
+
+#define log_error_errno(x, ...) LOG(ERROR, x ": %s", ##__VA_ARGS__, strerror(errno))
+
+struct log;
+struct log_target;
+
+attr_printf(4, 5) void log_printf(struct log *, int level, const char *func,
+ const char *fmt, ...);
+
+attr_malloc struct log *log_new(void);
+/// Destroy a log struct and every log target added to it
+attr_nonnull_all void log_destroy(struct log *);
+attr_nonnull(1) void log_set_level(struct log *l, int level);
+attr_pure enum log_level log_get_level(const struct log *l);
+attr_nonnull_all void log_add_target(struct log *, struct log_target *);
+attr_pure enum log_level string_to_log_level(const char *);
+/// Remove a previously added log target for a log struct, and destroy it. If the log
+/// target was never added, nothing happens.
+void log_remove_target(struct log *l, struct log_target *tgt);
+
+extern thread_local struct log *tls_logger;
+
+/// Create a thread local logger
+static inline void log_init_tls(void) {
+ tls_logger = log_new();
+}
+/// Set thread local logger log level
+static inline void log_set_level_tls(int level) {
+ assert(tls_logger);
+ log_set_level(tls_logger, level);
+}
+static inline attr_nonnull_all void log_add_target_tls(struct log_target *tgt) {
+ assert(tls_logger);
+ log_add_target(tls_logger, tgt);
+}
+
+static inline attr_nonnull_all void log_remove_target_tls(struct log_target *tgt) {
+ assert(tls_logger);
+ log_remove_target(tls_logger, tgt);
+}
+
+static inline attr_pure enum log_level log_get_level_tls(void) {
+ assert(tls_logger);
+ return log_get_level(tls_logger);
+}
+
+static inline void log_deinit_tls(void) {
+ assert(tls_logger);
+ log_destroy(tls_logger);
+ tls_logger = NULL;
+}
+
+attr_malloc struct log_target *stderr_logger_new(void);
+attr_malloc struct log_target *file_logger_new(const char *file);
+attr_malloc struct log_target *null_logger_new(void);
+attr_malloc struct log_target *gl_string_marker_logger_new(void);
+
+// vim: set noet sw=8 ts=8: