242 lines
4.9 KiB
C
Raw Normal View History

2025-04-28 12:25:20 +08:00
/**
* @file XNLogger.h
* @author jinchao
* @brief
* @version 1.0
* @date 2025-01-08
*
* @copyright Copyright (c) 2025 COMAC
*
*/
#pragma once
2025-05-20 15:39:40 +08:00
#include <string>
#include <mutex>
#include <fstream>
#include <chrono>
#include <filesystem>
2025-04-28 12:25:20 +08:00
#include <type_traits>
2025-05-20 15:39:40 +08:00
#include <iostream>
#include <iomanip>
#include <sstream>
2025-04-28 12:25:20 +08:00
/**
* @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
*/
2025-05-20 15:39:40 +08:00
void log(LogLevel level, const std::string &message);
2025-04-28 12:25:20 +08:00
/**
* @brief
* @param level
* @param enable
*/
void enableConsoleOutput(LogLevel level, bool enable);
/**
* @brief
* @param level
* @param enable
*/
void enableFileOutput(LogLevel level, bool enable);
private:
/**
* @brief
*/
2025-05-20 15:39:40 +08:00
XNLogger();
2025-04-28 12:25:20 +08:00
/**
* @brief
*/
~XNLogger();
/**
* @brief
*/
2025-05-20 15:39:40 +08:00
XNLogger(const XNLogger &) = delete;
2025-04-28 12:25:20 +08:00
/**
* @brief
*/
2025-05-20 15:39:40 +08:00
XNLogger &operator=(const XNLogger &) = delete;
2025-04-28 12:25:20 +08:00
/**
* @brief
*/
2025-05-20 15:39:40 +08:00
std::string logFilePath;
2025-04-28 12:25:20 +08:00
/**
* @brief
*/
bool consoleOutputEnabled[5];
/**
* @brief
*/
bool fileOutputEnabled[5];
/**
* @brief
*/
2025-05-20 15:39:40 +08:00
std::ofstream logFile;
2025-04-28 12:25:20 +08:00
/**
* @brief
*/
2025-05-20 15:39:40 +08:00
std::mutex mutex;
2025-04-28 12:25:20 +08:00
/**
* @brief
* @param level
* @return
*/
2025-05-20 15:39:40 +08:00
std::string logLevelToString(LogLevel level) const;
/**
* @brief
* @return
*/
std::string getCurrentTimeString() const;
2025-04-28 12:25:20 +08:00
/**
* @brief
*/
2025-05-20 15:39:40 +08:00
const std::string COLOR_RESET = "\033[0m";
2025-04-28 12:25:20 +08:00
/**
* @brief
*/
2025-05-20 15:39:40 +08:00
const std::string COLOR_DEBUG = "\033[34m"; // 蓝色
2025-04-28 12:25:20 +08:00
/**
* @brief
*/
2025-05-20 15:39:40 +08:00
const std::string COLOR_INFO = "\033[32m"; // 绿色
2025-04-28 12:25:20 +08:00
/**
* @brief
*/
2025-05-20 15:39:40 +08:00
const std::string COLOR_WARNING = "\033[33m"; // 黄色
2025-04-28 12:25:20 +08:00
/**
* @brief
*/
2025-05-20 15:39:40 +08:00
const std::string COLOR_ERROR = "\033[31m"; // 红色
2025-04-28 12:25:20 +08:00
};
/**
* @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
2025-05-20 15:39:40 +08:00
log(XNLogger::LogLevel level, const std::string &message, Args... args)
2025-04-28 12:25:20 +08:00
{
2025-05-20 15:39:40 +08:00
std::string formattedMessage = formatMessage(message, args...);
2025-04-28 12:25:20 +08:00
XNLogger::instance().log(level, formattedMessage);
}
/**
* @brief
* @param level
* @param message
*/
2025-05-20 15:39:40 +08:00
inline static void log(XNLogger::LogLevel level, const std::string &message)
2025-04-28 12:25:20 +08:00
{
XNLogger::instance().log(level, message);
}
private:
// 辅助函数,用于格式化消息
template <typename T>
2025-05-20 15:39:40 +08:00
static std::string convertToString(const T &arg)
2025-04-28 12:25:20 +08:00
{
if constexpr (std::is_arithmetic<T>::value) {
2025-05-20 15:39:40 +08:00
return std::to_string(arg); // 处理数值类型
2025-04-28 12:25:20 +08:00
} else {
2025-05-20 15:39:40 +08:00
return std::string(arg);
2025-04-28 12:25:20 +08:00
}
}
// 递归变参函数,用于处理多个参数
template <typename T, typename... Args>
2025-05-20 15:39:40 +08:00
static std::string formatMessage(const std::string &message, T arg, Args... args)
2025-04-28 12:25:20 +08:00
{
2025-05-20 15:39:40 +08:00
// 查找下一个参数占位符
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...);
2025-04-28 12:25:20 +08:00
}
// 基础情况
2025-05-20 15:39:40 +08:00
static std::string formatMessage(const std::string &message) { return message; }
2025-04-28 12:25:20 +08:00
};
/**
* @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__)