#ifndef AIRPORT_UTILS_LOGGER_H #define AIRPORT_UTILS_LOGGER_H #include #include #include #include #include #include enum class LogLevel { DEBUG, INFO, WARNING, ERROR }; class Logger { public: static void initialize(const std::string& filename, LogLevel level = LogLevel::INFO) { std::lock_guard lock(getMutex()); currentLevel() = level; logFile().open(filename, std::ios::app); } static void setLogLevel(LogLevel level) { std::lock_guard lock(getMutex()); currentLevel() = level; } template static void debug(Args... args) { if (currentLevel() <= LogLevel::DEBUG) { log("DEBUG", args...); } } template static void info(Args... args) { if (currentLevel() <= LogLevel::INFO) { log("INFO", args...); } } template static void warning(Args... args) { if (currentLevel() <= LogLevel::WARNING) { log("WARNING", args...); } } template static void error(Args... args) { if (currentLevel() <= LogLevel::ERROR) { log("ERROR", args...); } } private: static LogLevel& currentLevel() { static LogLevel level = LogLevel::INFO; return level; } static std::ofstream& logFile() { static std::ofstream file; return file; } static std::mutex& getMutex() { static std::mutex mutex; return mutex; } template static void log(const char* level, Args... args) { auto now = std::chrono::system_clock::now(); auto now_c = std::chrono::system_clock::to_time_t(now); auto now_ms = std::chrono::duration_cast( now.time_since_epoch()) % 1000; std::stringstream ss; ss << std::put_time(std::localtime(&now_c), "%Y-%m-%d %H:%M:%S") << '.' << std::setfill('0') << std::setw(3) << now_ms.count() << " [" << level << "] "; ss << std::fixed << std::setprecision(14); (ss << ... << args) << std::endl; std::lock_guard lock(getMutex()); std::cerr << ss.str(); if (logFile().is_open()) { logFile() << ss.str(); logFile().flush(); } } }; #endif // AIRPORT_UTILS_LOGGER_H