// core/Logger.h #pragma once #include #include #include #include #include #include #include enum class LogLevel { Debug, Info, Warning, Error, Fatal }; #define LOG_D(msg) Logger::Log(LogLevel::Debug, CURRENT_MODULE, __func__, msg) #define LOG_I(msg) Logger::Log(LogLevel::Info, CURRENT_MODULE, __func__, msg) #define LOG_W(msg) Logger::Log(LogLevel::Warning, CURRENT_MODULE, __func__, msg) #define LOG_E(msg) Logger::Log(LogLevel::Error, CURRENT_MODULE, __func__, msg) #define LOG_F(msg) Logger::Log(LogLevel::Fatal, CURRENT_MODULE, __func__, msg) class Logger { static std::mutex mtx; static std::string GetTime() { auto now = std::chrono::system_clock::now(); auto tt = std::chrono::system_clock::to_time_t(now); auto ms = std::chrono::duration_cast(now.time_since_epoch()) % 1000; tm local{}; localtime_s(&local, &tt); std::ostringstream oss; oss << std::put_time(&local, "%Y-%m-%d %H:%M:%S") << '.' << std::setfill('0') << std::setw(3) << ms.count(); return oss.str(); } static char LevelChar(LogLevel lv) { switch (lv) { case LogLevel::Debug: return 'D'; case LogLevel::Info: return 'I'; case LogLevel::Warning: return 'W'; case LogLevel::Error: return 'E'; case LogLevel::Fatal: return 'F'; default: return '?'; } } public: template static void Log(LogLevel level, const char* module, const char* func, const std::string& message) { std::lock_guard lock(mtx); std::ostringstream oss; oss << "[" << GetTime() << "] " << std::left << std::setw(40) << (std::string(module) + "::" + func + "()") << LevelChar(level) << " : " << message; std::cout << oss.str() << std::endl; OutputDebugStringA((oss.str() + "\n").c_str()); } };