/** * @file log.h * @brief 日志系统核心模块(支持多级日志、断言和异常处理) */ #ifndef __SCC_LOG_IMPL_H__ #define __SCC_LOG_IMPL_H__ #include "color.h" #include #ifdef __SCC_LOG_IMPL_USE_STD_IMPL__ #include #include #define log_vsnprintf vsnprintf #define log_puts puts #define log_exit scc_exit #endif #ifdef __GNUC__ // GCC, Clang, ICC #define __smcc_log_unreachable() (__builtin_unreachable()) #elif defined _MSC_VER // MSVC #define __smcc_log_unreachable() (__assume(false)) #elif defined __SMCC_BUILT_IN__ // The SMCC (my compiler) #define __smcc_log_unreachable() (__smcc_builtin_unreachable()) #else #define __smcc_log_unreachable() #endif #ifndef log_vsnprintf #define log_vsnprintf(...) #warning "log_vsnprintf not defined" #endif #ifndef log_puts #define log_puts(...) #warning "log_puts not defined" #endif #ifndef log_exit #define log_exit(...) #warning "log_exit not defined" #endif /** * @brief 日志级别枚举 * * 定义日志系统的输出级别和组合标志位 */ typedef enum log_level { LOG_LEVEL_NOTSET = 0, ///< 未设置级别(继承默认配置) LOG_LEVEL_DEBUG = 1 << 0, ///< 调试信息(开发阶段详细信息) LOG_LEVEL_INFO = 1 << 1, ///< 常规信息(系统运行状态) LOG_LEVEL_WARN = 1 << 2, ///< 警告信息(潜在问题提示) LOG_LEVEL_ERROR = 1 << 3, ///< 错误信息(可恢复的错误) LOG_LEVEL_FATAL = 1 << 4, ///< 致命错误(导致程序终止的严重错误) LOG_LEVEL_TRACE = 1 << 5, ///< 追踪(性能追踪或者栈帧追踪) LOG_LEVEL_ALL = 0xFF, ///< 全级别标志(组合所有日志级别) } log_level_t; #ifndef LOGGER_MAX_BUF_SIZE #define LOGGER_MAX_BUF_SIZE 512 ///< 单条日志最大缓冲区尺寸 #endif typedef struct logger logger_t; typedef int (*log_handler)(logger_t *module, log_level_t level, const char *file, int line, const char *func, const char *fmt, ...); /** * @brief 日志器实例结构体 * * 每个日志器实例维护独立的配置和缓冲区 */ struct logger { const char *name; ///< 日志器名称(用于模块区分) log_level_t level; ///< 当前设置的日志级别 log_handler handler; ///< 日志处理回调函数 char buf[LOGGER_MAX_BUF_SIZE]; ///< 格式化缓冲区 }; int log_default_handler(logger_t *module, log_level_t level, const char *file, int line, const char *func, const char *fmt, ...); extern logger_t __default_logger_root; /** * @brief 初始化日志实例 其余参数设置为默认值 * @param[in] logger 日志器实例指针 * @param[in] name 日志器名称(NULL表示获取默认日志器名称) */ void init_logger(logger_t *logger, const char *name); /** * @brief 设置日志级别 * @param[in] logger 目标日志器实例 * @param[in] level 要设置的日志级别(可组合多个级别) */ void log_set_level(logger_t *logger, int level); /** * @brief 设置自定义日志处理器 * @param[in] logger 目标日志器实例 * @param[in] handler 自定义处理函数(NULL恢复默认处理) */ void log_set_handler(logger_t *logger, log_handler handler); #ifndef LOG_MAX_MAROC_BUF_SIZE #define LOG_MAX_MAROC_BUF_SIZE LOGGER_MAX_BUF_SIZE ///< 宏展开缓冲区尺寸 #endif #define SCC_LOG_HANDLE_ARGS(_module_, _level_, ...) \ (_module_), (_level_), __FILE__, __LINE__, __func__, ##__VA_ARGS__ #define SCC_LOG_IMPL(_module_, _level_, _fmt_, ...) \ do { \ /* TODO check _module_ is NULL */ \ if ((_module_)->handler && ((_module_)->level & (_level_))) \ (_module_)->handler( \ SCC_LOG_HANDLE_ARGS(_module_, _level_, _fmt_, ##__VA_ARGS__)); \ } while (0) /* clang-format off */ /// @name 模块日志宏 /// @{ #define MLOG_NOTSET(module, ...)SCC_LOG_IMPL(module, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志 #define MLOG_DEBUG(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志(需启用DEBUG级别) #define MLOG_INFO(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志) #define MLOG_WARN(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_WARN, __VA_ARGS__) ///< 警告日志(潜在问题) #define MLOG_ERROR(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_ERROR, __VA_ARGS__) ///< 错误日志(可恢复错误) #define MLOG_FATAL(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_FATAL, __VA_ARGS__) ///< 致命错误日志(程序终止前) #define MLOG_TRACE(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_TRACE, __VA_ARGS__) ///< 追踪日志(调用栈跟踪) /// @} /// @name 快捷日志宏 /// @{ #define LOG_NOTSET(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志 #define LOG_DEBUG(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志(需启用DEBUG级别) #define LOG_INFO(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志) #define LOG_WARN(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_WARN, __VA_ARGS__) ///< 警告日志(潜在问题) #define LOG_ERROR(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_ERROR, __VA_ARGS__) ///< 错误日志(可恢复错误) #define LOG_FATAL(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_FATAL, __VA_ARGS__) ///< 致命错误日志(程序终止前) #define LOG_TRACE(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_TRACE, __VA_ARGS__) ///< 追踪日志(调用栈跟踪) /// @} /* clang-format on */ /** * @def _Assert * @brief 断言检查内部宏 * @param cond 检查条件表达式 * @param ... 错误信息参数(格式字符串+参数) */ #define _Assert(cond, ...) \ ((void)((cond) || \ (__default_logger_root.handler(SCC_LOG_HANDLE_ARGS( \ &__default_logger_root, LOG_LEVEL_FATAL, __VA_ARGS__)), \ log_exit(1), __smcc_log_unreachable(), 0))) /// @name 断言工具宏 /// @{ #define __INNERSCC_LOG_IMPL_STR(str) #str #define _SCC_LOG_IMPL_STR(str) __INNERSCC_LOG_IMPL_STR(str) #define AssertFmt(cond, format, ...) \ _Assert(cond, "Assertion Failure: " format, \ ##__VA_ARGS__) ///< 带格式的断言检查 #define PanicFmt(format, ...) \ _Assert(0, "Panic: " format, ##__VA_ARGS__) ///< 立即触发致命错误 #define Assert(cond) \ AssertFmt(cond, "cond is `" _SCC_LOG_IMPL_STR(cond) "`") ///< 基础断言检查 #define Panic(...) PanicFmt(__VA_ARGS__) ///< 触发致命错误(带自定义消息) #define TODO() \ PanicFmt("TODO please implement me") ///< 标记未实现代码(触发致命错误) #define UNREACHABLE() PanicFmt("UNREACHABLE") ///< 触发致命错误(代码不可达) #define FIXME(str) \ PanicFmt("FIXME " _SCC_LOG_IMPL_STR( \ str)) ///< 提醒开发者修改代码(触发致命错误) /// @} /** * @brief 静态断言(编译时) * * 利用数组大小不能为负的特性 * 或使用 _Static_assert (C11) */ #ifdef static_assert #undef static_assert #endif #if __STDC_VERSION__ >= 201112L #define static_assert _Static_assert #else #define static_assert(cond, msg) extern char __static_assertion[(cond) ? 1 : -1] #endif #ifdef __SCC_LOG_IMPL_IMPORT_SRC__ #include "log.c" #endif #endif /* __SCC_LOG_IMPL_H__ */