/** * @file mcp_logger.h * @brief Simple logger */ #ifndef MCP_LOGGER_H #define MCP_LOGGER_H #include #include #include #include #include #include namespace mcp { enum class log_level { debug, info, warning, error }; class logger { public: static logger& instance() { static logger instance; return instance; } void set_level(log_level level) { std::lock_guard lock(mutex_); level_ = level; } template void debug(Args&&... args) { log(log_level::debug, std::forward(args)...); } template void info(Args&&... args) { log(log_level::info, std::forward(args)...); } template void warning(Args&&... args) { log(log_level::warning, std::forward(args)...); } template void error(Args&&... args) { log(log_level::error, std::forward(args)...); } private: logger() : level_(log_level::info) {} template void log_impl(std::stringstream& ss, T&& arg) { ss << std::forward(arg); } template void log_impl(std::stringstream& ss, T&& arg, Args&&... args) { ss << std::forward(arg); log_impl(ss, std::forward(args)...); } template void log(log_level level, Args&&... args) { if (level < level_) { return; } std::stringstream ss; // Add timestamp auto now = std::chrono::system_clock::now(); auto now_c = std::chrono::system_clock::to_time_t(now); auto now_tm = std::localtime(&now_c); ss << std::put_time(now_tm, "%Y-%m-%d %H:%M:%S") << " "; // Add log level and color switch (level) { case log_level::debug: ss << "\033[36m[DEBUG]\033[0m "; // Cyan break; case log_level::info: ss << "\033[32m[INFO]\033[0m "; // Green break; case log_level::warning: ss << "\033[33m[WARNING]\033[0m "; // Yellow break; case log_level::error: ss << "\033[31m[ERROR]\033[0m "; // Red break; } // Add log content log_impl(ss, std::forward(args)...); // Output log std::lock_guard lock(mutex_); std::cerr << ss.str() << std::endl; } log_level level_; std::mutex mutex_; }; #define LOG_DEBUG(...) mcp::logger::instance().debug(__VA_ARGS__) #define LOG_INFO(...) mcp::logger::instance().info(__VA_ARGS__) #define LOG_WARNING(...) mcp::logger::instance().warning(__VA_ARGS__) #define LOG_ERROR(...) mcp::logger::instance().error(__VA_ARGS__) inline void set_log_level(log_level level) { mcp::logger::instance().set_level(level); } } // namespace mcp #endif // MCP_LOGGER_H