#include "logger.hpp" #include namespace custom { Logger& Logger::getInstance() { static Logger instance; return instance; } void Logger::setLevel(LogLevel level) { std::lock_guard lock(logMutex_); currentLevel_ = level; } void Logger::setLogFile(const std::string& filename) { std::lock_guard lock(logMutex_); if (logFile_) { logFile_->close(); } logFile_ = std::make_unique(filename, std::ios::app); if (!logFile_->is_open()) { std::cerr << "Failed to open log file: " << filename << std::endl; logFile_.reset(); } } void Logger::log(LogLevel level, const std::string& message) { if (level < currentLevel_) { return; } std::lock_guard lock(logMutex_); std::string timestamp = getCurrentTime(); std::string levelStr = levelToString(level); std::string logMessage = "[" + timestamp + "] [" + levelStr + "] " + message; // Always log to console std::cout << logMessage << std::endl; // Log to file if available if (logFile_ && logFile_->is_open()) { *logFile_ << logMessage << std::endl; logFile_->flush(); } } void Logger::debug(const std::string& message) { log(LogLevel::DEBUG, message); } void Logger::info(const std::string& message) { log(LogLevel::INFO, message); } void Logger::warn(const std::string& message) { log(LogLevel::WARN, message); } void Logger::error(const std::string& message) { log(LogLevel::ERROR, message); } std::string Logger::getCurrentTime() { auto now = std::chrono::system_clock::now(); auto time_t = std::chrono::system_clock::to_time_t(now); auto ms = std::chrono::duration_cast( now.time_since_epoch()) % 1000; std::stringstream ss; ss << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S"); ss << "." << std::setfill('0') << std::setw(3) << ms.count(); return ss.str(); } std::string Logger::levelToString(LogLevel level) { switch (level) { case LogLevel::DEBUG: return "DEBUG"; case LogLevel::INFO: return "INFO "; case LogLevel::WARN: return "WARN "; case LogLevel::ERROR: return "ERROR"; default: return "UNKNOWN"; } } } // namespace custom