242 lines
4.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file XNLogger.h
* @author jinchao
* @brief 日志类
* @version 1.0
* @date 2025-01-08
*
* @copyright Copyright (c) 2025 COMAC
*
*/
#pragma once
#include <string>
#include <mutex>
#include <fstream>
#include <chrono>
#include <filesystem>
#include <type_traits>
#include <iostream>
#include <iomanip>
#include <sstream>
/**
* @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 std::string &message);
/**
* @brief 启用控制台输出
* @param level 日志等级
* @param enable 是否启用
*/
void enableConsoleOutput(LogLevel level, bool enable);
/**
* @brief 启用文件输出
* @param level 日志等级
* @param enable 是否启用
*/
void enableFileOutput(LogLevel level, bool enable);
private:
/**
* @brief 构造函数
*/
XNLogger();
/**
* @brief 析构函数
*/
~XNLogger();
/**
* @brief 禁止拷贝构造
*/
XNLogger(const XNLogger &) = delete;
/**
* @brief 禁止赋值
*/
XNLogger &operator=(const XNLogger &) = delete;
/**
* @brief 日志文件路径
*/
std::string logFilePath;
/**
* @brief 控制台输出控制
*/
bool consoleOutputEnabled[5];
/**
* @brief 文件输出控制
*/
bool fileOutputEnabled[5];
/**
* @brief 日志文件
*/
std::ofstream logFile;
/**
* @brief 互斥锁
*/
std::mutex mutex;
/**
* @brief 日志等级转换为字符串
* @param level 日志等级
* @return 日志等级字符串
*/
std::string logLevelToString(LogLevel level) const;
/**
* @brief 获取当前时间字符串
* @return 格式化的时间字符串
*/
std::string getCurrentTimeString() const;
/**
* @brief 控制台输出字体恢复颜色常量
*/
const std::string COLOR_RESET = "\033[0m";
/**
* @brief 调试颜色常量
*/
const std::string COLOR_DEBUG = "\033[34m"; // 蓝色
/**
* @brief 信息颜色常量
*/
const std::string COLOR_INFO = "\033[32m"; // 绿色
/**
* @brief 警告颜色常量
*/
const std::string COLOR_WARNING = "\033[33m"; // 黄色
/**
* @brief 错误颜色常量
*/
const std::string COLOR_ERROR = "\033[31m"; // 红色
};
/**
* @brief 日志辅助类
*/
class XNLoggerHelper
{
public:
/**
* @brief 带参数的日志输出
* @tparam Args 参数类型
* @param level 日志等级
* @param message 日志消息
* @param args 参数
*/
template <typename... Args>
inline static typename std::enable_if<(sizeof...(Args) > 0), void>::type
log(XNLogger::LogLevel level, const std::string &message, Args... args)
{
std::string formattedMessage = formatMessage(message, args...);
XNLogger::instance().log(level, formattedMessage);
}
/**
* @brief 不带参数的日志输出
* @param level 日志等级
* @param message 日志消息
*/
inline static void log(XNLogger::LogLevel level, const std::string &message)
{
XNLogger::instance().log(level, message);
}
private:
// 辅助函数,用于格式化消息
template <typename T>
static std::string convertToString(const T &arg)
{
if constexpr (std::is_arithmetic<T>::value) {
return std::to_string(arg); // 处理数值类型
} else {
return std::string(arg);
}
}
// 递归变参函数,用于处理多个参数
template <typename T, typename... Args>
static std::string formatMessage(const std::string &message, T arg, Args... args)
{
// 查找下一个参数占位符
std::string result = message;
size_t paramIndex = 0;
size_t pos = 0;
// 找到当前参数对应的占位符
while (true) {
std::string placeholder = "%" + std::to_string(paramIndex + 1);
pos = result.find(placeholder);
if (pos != std::string::npos) {
// 替换占位符使用placeholder的长度
result.replace(pos, placeholder.length(), convertToString(arg));
break;
}
paramIndex++;
if (paramIndex > 100) { // 防止无限循环
return result;
}
}
return formatMessage(result, args...);
}
// 基础情况
static std::string formatMessage(const std::string &message) { return message; }
};
/**
* @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__)