2025-04-28 12:25:20 +08:00
|
|
|
#include "XNLogger.h"
|
|
|
|
|
|
|
|
XNLogger::XNLogger()
|
|
|
|
: consoleOutputEnabled{true, true, true, true}, fileOutputEnabled{true, true, true, true}
|
|
|
|
{
|
|
|
|
// 获取当前工作目录
|
2025-05-20 15:39:40 +08:00
|
|
|
std::filesystem::path currentDir = std::filesystem::current_path();
|
|
|
|
std::filesystem::path logDirPath = currentDir / "log";
|
2025-04-28 12:25:20 +08:00
|
|
|
|
|
|
|
// 创建 log 文件夹
|
2025-05-20 15:39:40 +08:00
|
|
|
if (!std::filesystem::exists(logDirPath)) {
|
|
|
|
std::filesystem::create_directories(logDirPath);
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 创建以当前日期和时间命名的日志文件
|
2025-05-20 15:39:40 +08:00
|
|
|
auto now = std::chrono::system_clock::now();
|
|
|
|
auto time = std::chrono::system_clock::to_time_t(now);
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << std::put_time(std::localtime(&time), "%Y%m%d_%H%M%S");
|
|
|
|
std::string logFileName = "log_" + ss.str() + ".log";
|
2025-04-28 12:25:20 +08:00
|
|
|
|
2025-05-20 15:39:40 +08:00
|
|
|
logFilePath = (logDirPath / logFileName).string();
|
|
|
|
logFile.open(logFilePath, std::ios::app);
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
XNLogger::~XNLogger()
|
|
|
|
{
|
2025-05-20 15:39:40 +08:00
|
|
|
if (logFile.is_open()) {
|
2025-04-28 12:25:20 +08:00
|
|
|
logFile.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-20 15:39:40 +08:00
|
|
|
std::string XNLogger::getCurrentTimeString() const
|
2025-04-28 12:25:20 +08:00
|
|
|
{
|
2025-05-20 15:39:40 +08:00
|
|
|
auto now = std::chrono::system_clock::now();
|
|
|
|
auto time = std::chrono::system_clock::to_time_t(now);
|
|
|
|
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
|
2025-04-28 12:25:20 +08:00
|
|
|
|
2025-05-20 15:39:40 +08:00
|
|
|
std::stringstream ss;
|
|
|
|
ss << std::put_time(std::localtime(&time), "%Y-%m-%d %H:%M:%S");
|
|
|
|
ss << '.' << std::setfill('0') << std::setw(3) << ms.count();
|
|
|
|
return ss.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
void XNLogger::log(LogLevel level, const std::string &message)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> locker(mutex);
|
|
|
|
std::string logMessage =
|
|
|
|
"[" + getCurrentTimeString() + "] [" + logLevelToString(level) + "] " + message;
|
|
|
|
|
|
|
|
std::string coloredMessage;
|
2025-04-28 12:25:20 +08:00
|
|
|
|
|
|
|
// 根据日志等级设置颜色
|
|
|
|
switch (level) {
|
|
|
|
case Debug:
|
|
|
|
coloredMessage = COLOR_DEBUG + logMessage + COLOR_RESET;
|
|
|
|
break;
|
|
|
|
case Info:
|
|
|
|
coloredMessage = COLOR_INFO + logMessage + COLOR_RESET;
|
|
|
|
break;
|
|
|
|
case Warning:
|
|
|
|
coloredMessage = COLOR_WARNING + logMessage + COLOR_RESET;
|
|
|
|
break;
|
|
|
|
case Error:
|
|
|
|
coloredMessage = COLOR_ERROR + logMessage + COLOR_RESET;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
coloredMessage = logMessage; // 默认无颜色
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 控制台输出
|
|
|
|
if (consoleOutputEnabled[level]) {
|
|
|
|
if (level == Time) {
|
|
|
|
// 如果是时间日志,则不换行,回退到该行开始
|
2025-05-20 15:39:40 +08:00
|
|
|
std::cout << coloredMessage << "\r" << std::flush;
|
2025-04-28 12:25:20 +08:00
|
|
|
} else {
|
2025-05-20 15:39:40 +08:00
|
|
|
std::cout << coloredMessage << std::endl;
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 文件输出
|
2025-05-20 15:39:40 +08:00
|
|
|
if (fileOutputEnabled[level] && logFile.is_open()) {
|
2025-04-28 12:25:20 +08:00
|
|
|
if (level == Time) {
|
2025-05-20 15:39:40 +08:00
|
|
|
logFile << logMessage << "\r" << std::flush;
|
2025-04-28 12:25:20 +08:00
|
|
|
} else {
|
2025-05-20 15:39:40 +08:00
|
|
|
logFile << logMessage << std::endl;
|
2025-04-28 12:25:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void XNLogger::enableConsoleOutput(LogLevel level, bool enable)
|
|
|
|
{
|
|
|
|
consoleOutputEnabled[level] = enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
void XNLogger::enableFileOutput(LogLevel level, bool enable)
|
|
|
|
{
|
|
|
|
fileOutputEnabled[level] = enable;
|
|
|
|
}
|
|
|
|
|
2025-05-20 15:39:40 +08:00
|
|
|
std::string XNLogger::logLevelToString(LogLevel level) const
|
2025-04-28 12:25:20 +08:00
|
|
|
{
|
|
|
|
switch (level) {
|
|
|
|
case Debug:
|
|
|
|
return "DEBUG";
|
|
|
|
case Info:
|
|
|
|
return "INFO";
|
|
|
|
case Warning:
|
|
|
|
return "WARNING";
|
|
|
|
case Error:
|
|
|
|
return "ERROR";
|
|
|
|
case Time:
|
|
|
|
return "TIME";
|
|
|
|
default:
|
|
|
|
return "UNKNOWN";
|
|
|
|
}
|
|
|
|
}
|