#ifndef _H_LOGGER_H #define _H_LOGGER_H #include #include #include #include #define LOG(lvl, msg, ...) Logger::getInstance()->log(lvl, msg, __VA_ARGS__) #define ERROR_LOG(msg, ...) {Logger::getInstance()->log(ERROR, msg, __VA_ARGS__); return false;} #define LOG_LEVEL(lvl) Logger::getInstance()->setLevel(lvl) enum LogLevel {DEBUG, INFO, WARN, ERROR}; class Logger { public: static Logger* getInstance(); template void log(LogLevel level, const std::string& message, Args... args) const { if (level >= currentLogLevel) { std::lock_guard lock(mutex); auto msg = formatString(message, args...); std::cout << "[" << std::format("{:%m-%d-%Y %X}", std::chrono::current_zone()->to_local(std::chrono::system_clock::now())) << "] " << msg << std::endl; } } void setLevel(LogLevel level) { currentLogLevel = level; } Logger(const Logger& l) = delete; void operator=(const Logger& l) = delete; protected: Logger() { }; ~Logger() { }; LogLevel currentLogLevel = INFO; template std::string formatString(const std::string& str, Args... args) const { return std::vformat(str, std::make_format_args(args...)); } private: static Logger* instance; static std::mutex mutex; }; #endif