/** * @file XNLogger.h * @author jinchao * @brief 日志类 * @version 1.0 * @date 2025-01-08 * * @copyright Copyright (c) 2025 COMAC * */ #pragma once #include "XNCore_Function.h" #include "XNTypeDefine.h" #include "XNTypeTraits.h" /** * @brief 日志类 */ class XNLogger { public: /** * @brief 日志等级 */ enum LogLevel { Debug, Info, Warning, Error, Time }; /** * @brief 获取日志类实例 * @return 日志类实例 */ static XNLogger &instance() { static XNLogger instance; return instance; } /** * @brief 日志输出 * @param level 日志等级 * @param message 日志消息 */ void log(LogLevel level, const XN_STRING &message); /** * @brief 启用控制台输出 * @param level 日志等级 * @param enable 是否启用 */ void enableConsoleOutput(LogLevel level, XN_BOOL enable); /** * @brief 启用文件输出 * @param level 日志等级 * @param enable 是否启用 */ void enableFileOutput(LogLevel level, XN_BOOL enable); private: /** * @brief 构造函数 */ XNLogger(); /** * @brief 析构函数 */ ~XNLogger(); /** * @brief 禁止拷贝构造 */ XNLogger(const XNLogger &) = delete; /** * @brief 禁止赋值 */ XNLogger &operator=(const XNLogger &) = delete; /** * @brief 日志文件路径 */ XN_STRING logFilePath; /** * @brief 控制台输出控制 */ XN_BOOL consoleOutputEnabled[5]; /** * @brief 文件输出控制 */ XN_BOOL fileOutputEnabled[5]; /** * @brief 日志文件 */ XN_OFSTREAM logFile; /** * @brief 互斥锁 */ XN_MUTEX mutex; /** * @brief 日志等级转换为字符串 * @param level 日志等级 * @return 日志等级字符串 */ XN_STRING logLevelToString(LogLevel level) const; /** * @brief 获取当前时间字符串 * @return 格式化的时间字符串 */ XN_STRING getCurrentTimeString() const; /** * @brief 控制台输出字体恢复颜色常量 */ const XN_STRING COLOR_RESET = "\033[0m"; /** * @brief 调试颜色常量 */ const XN_STRING COLOR_DEBUG = "\033[34m"; // 蓝色 /** * @brief 信息颜色常量 */ const XN_STRING COLOR_INFO = "\033[32m"; // 绿色 /** * @brief 警告颜色常量 */ const XN_STRING COLOR_WARNING = "\033[33m"; // 黄色 /** * @brief 错误颜色常量 */ const XN_STRING COLOR_ERROR = "\033[31m"; // 红色 }; /** * @brief 日志辅助类 */ class XNLoggerHelper { public: /** * @brief 带参数的日志输出 * @tparam Args 参数类型 * @param level 日志等级 * @param message 日志消息 * @param args 参数 */ template inline static typename std::enable_if<(sizeof...(Args) > 0), void>::type log(XNLogger::LogLevel level, const XN_STRING &message, Args... args) { XN_STRING formattedMessage = formatMessage(message, args...); XNLogger::instance().log(level, formattedMessage); } /** * @brief 不带参数的日志输出 * @param level 日志等级 * @param message 日志消息 */ inline static void log(XNLogger::LogLevel level, const XN_STRING &message) { XNLogger::instance().log(level, message); } private: /** * @brief 将参数转换为字符串 * @tparam T 参数类型 * @param arg 要转换的参数 * @return 转换后的字符串 */ template static XN_STRING convertToString(const T &arg) { if constexpr (XNSim::is_arithmetic_v) { return std::to_string(arg); // 处理数值类型 } else if constexpr (XNSim::is_same_v) { return arg; } else if constexpr (XNSim::is_convertible_v) { return XN_STRING(arg); } else if constexpr (XNSim::is_same_v || XNSim::is_same_v) { return XN_STRING(arg); } else { static_assert(XNSim::is_arithmetic_v || XNSim::is_same_v || XNSim::is_convertible_v || XNSim::is_same_v || XNSim::is_same_v, "A01021001: 不支持的类型转换,详见XNLogger.cpp:line 199"); } } /** * @brief 格式化日志消息,顺序替换%1、%2、%3…… * @tparam Args 参数类型 * @param message 日志消息 * @param args 参数包 * @return 格式化后的消息 */ template static XN_STRING formatMessage(const XN_STRING &message, Args &&...args) { static_assert( sizeof...(Args) <= 9, "A01021002: 单条日志参数数量超过限制,详见XNLogger.cpp:line 216"); XN_STRING result = message; // 使用初始化列表展开参数包 int index = 1; // 使用lambda和std::initializer_list展开参数包 (void)std::initializer_list{( [&result, &index](const auto &value) { XN_STRING placeholder = "%" + ToXNString(index++); size_t pos = result.find(placeholder); if (pos != XN_STRING::npos) { result.replace(pos, placeholder.length(), convertToString(value)); } }(args), 0)...}; return result; } }; /** * @brief 宏定义,用于输出调试日志 */ #define LOG_DEBUG(message, ...) \ XNLoggerHelper::log(XNLogger::Debug, message, ##__VA_ARGS__) /** * @brief 宏定义,用于输出信息日志 */ #define LOG_INFO(message, ...) \ XNLoggerHelper::log(XNLogger::Info, message, ##__VA_ARGS__) /** * @brief 宏定义,用于输出警告日志 */ #define LOG_WARNING(message, ...) \ XNLoggerHelper::log(XNLogger::Warning, message, ##__VA_ARGS__) /** * @brief 宏定义,用于输出错误日志 */ #define LOG_ERROR(message, ...) \ XNLoggerHelper::log(XNLogger::Error, message, ##__VA_ARGS__)