#include static inline int log_snprintf(char *s, size_t n, const char *format, ...) { int ret; va_list args; va_start(args, format); ret = log_vsnprintf(s, n, format, args); va_end(args); return ret; } int log_default_handler(logger_t *module, log_level_t level, const char *file, int line, const char *func, const char *fmt, ...) { const char *level_str; int offset = 0; va_list args; va_start(args, fmt); /* clang-format off */ switch (level) { case LOG_LEVEL_DEBUG: level_str = "DEBUG"; break; case LOG_LEVEL_INFO: level_str = "INFO "; break; case LOG_LEVEL_WARN: level_str = "WARN "; break; case LOG_LEVEL_ERROR: level_str = "ERROR"; break; case LOG_LEVEL_FATAL: level_str = "FATAL"; break; case LOG_LEVEL_TRACE: level_str = "TRACE"; break; default: level_str = "NOTSET"; break; } /// @note: 定义 __LOG_NO_COLOR__ 会取消颜色输出 #ifndef __LOG_NO_COLOR__ const char *color_code; switch (level) { case LOG_LEVEL_DEBUG: color_code = ANSI_FG_CYAN; break; case LOG_LEVEL_INFO: color_code = ANSI_FG_GREEN; break; case LOG_LEVEL_TRACE: color_code = ANSI_FG_BLUE; break; case LOG_LEVEL_WARN: color_code = ANSI_FG_YELLOW; break; case LOG_LEVEL_ERROR: color_code = ANSI_FG_RED; break; case LOG_LEVEL_FATAL: color_code = ANSI_FG_RED ANSI_UNDERLINED; break; default: color_code = ANSI_NONE; } /* clang-format on */ offset = log_snprintf(module->buf, sizeof(module->buf), ANSI_BOLD "%s[%s] %s - %s:%d in %s()" ANSI_NONE " ", color_code, level_str, module->name, file, line, func); #else offset = log_snprintf(module->buf, sizeof(module->buf), "[%s] %s - %s:%d in %s() ", level_str, module->name, file, line, func); #endif /* 然后写入用户消息(如果有) */ if (fmt && fmt[0]) { log_vsnprintf(module->buf + offset, sizeof(module->buf) - offset, fmt, args); } va_end(args); log_puts(module->buf); log_puts("\n"); // for clangd warning // clang-analyzer-deadcode.DeadStores (void)color_code; (void)level_str; if (level & LOG_LEVEL_FATAL) { log_exit(-LOG_LEVEL_FATAL); } return 0; } logger_t __default_logger_root = { .name = "root", .level = LOG_LEVEL_ALL, .handler = log_default_handler, }; void init_logger(logger_t *logger, const char *name) { logger->name = name; logger->handler = log_default_handler; log_set_level(logger, LOG_LEVEL_ALL); } void log_set_level(logger_t *logger, int level) { if (logger) logger->level = level; else __default_logger_root.level = level; } void log_set_handler(logger_t *logger, log_handler handler) { if (logger) logger->handler = handler; else __default_logger_root.handler = handler; }