#pragma once #include #include #include #include #include #include #include namespace custom { enum class LogLevel { DEBUG = 0, INFO = 1, WARN = 2, ERROR = 3 }; class Logger { public: static Logger& getInstance(); void setLevel(LogLevel level); void setLogFile(const std::string& filename); void log(LogLevel level, const std::string& message); void debug(const std::string& message); void info(const std::string& message); void warn(const std::string& message); void error(const std::string& message); template void log(LogLevel level, const char* format, Args... args); template void debug(const char* format, Args... args); template void info(const char* format, Args... args); template void warn(const char* format, Args... args); template void error(const char* format, Args... args); private: Logger() = default; ~Logger() = default; Logger(const Logger&) = delete; Logger& operator=(const Logger&) = delete; std::string getCurrentTime(); std::string levelToString(LogLevel level); LogLevel currentLevel_ = LogLevel::INFO; std::unique_ptr logFile_; std::mutex logMutex_; }; // Convenience macros #define LOG_DEBUG(msg, ...) custom::Logger::getInstance().debug(msg, ##__VA_ARGS__) #define LOG_INFO(msg, ...) custom::Logger::getInstance().info(msg, ##__VA_ARGS__) #define LOG_WARN(msg, ...) custom::Logger::getInstance().warn(msg, ##__VA_ARGS__) #define LOG_ERROR(msg, ...) custom::Logger::getInstance().error(msg, ##__VA_ARGS__) } // namespace custom