#ifndef LOGGER_H #define LOGGER_H #include #include #include #include #include #include #include /** * @brief Log level enumeration */ enum class LogLevel { DEBUG, INFO, WARNING, ERROR }; /** * @brief Logger type enumeration */ enum class LoggerType { HTTP, // HTTP access logs INTERNAL // Internal operation logs }; /** * @brief Simple logger with file and console output support * * Designed to be systemd-friendly with structured logging format */ class Logger { public: /** * @brief Get the singleton logger instance */ static Logger& getInstance(); /** * @brief Initialize the logger * * @param enableFileLogging Enable logging to file * @param logFilePath Path to log file (if file logging enabled) * @param minLevel Minimum log level to output */ void initialize(bool enableFileLogging = false, const std::string& logFilePath = "", LogLevel minLevel = LogLevel::INFO); /** * @brief Log a message * * @param level Log level * @param message Message to log * @param type Logger type (HTTP or INTERNAL) */ void log(LogLevel level, const std::string& message, LoggerType type = LoggerType::INTERNAL); /** * @brief Log debug message */ void debug(const std::string& message, LoggerType type = LoggerType::INTERNAL) { log(LogLevel::DEBUG, message, type); } /** * @brief Log info message */ void info(const std::string& message, LoggerType type = LoggerType::INTERNAL) { log(LogLevel::INFO, message, type); } /** * @brief Log warning message */ void warning(const std::string& message, LoggerType type = LoggerType::INTERNAL) { log(LogLevel::WARNING, message, type); } /** * @brief Log error message */ void error(const std::string& message, LoggerType type = LoggerType::INTERNAL) { log(LogLevel::ERROR, message, type); } /** * @brief Set minimum log level for specific logger type */ void setLogLevel(LoggerType type, LogLevel level); /** * @brief Get minimum log level for specific logger type */ LogLevel getLogLevel(LoggerType type) const; /** * @brief Check if file logging is enabled */ bool isFileLoggingEnabled() const { return m_fileLoggingEnabled; } /** * @brief Get current log file path */ std::string getLogFilePath() const { return m_logFilePath; } /** * @brief Close log file */ void close(); private: Logger() = default; ~Logger(); // Prevent copying Logger(const Logger&) = delete; Logger& operator=(const Logger&) = delete; std::string getCurrentTimestamp(); std::string levelToString(LogLevel level); std::string levelToSystemdPriority(LogLevel level); std::string typeToString(LoggerType type); bool m_fileLoggingEnabled = false; std::string m_logFilePath; LogLevel m_httpMinLevel = LogLevel::INFO; LogLevel m_internalMinLevel = LogLevel::INFO; std::ofstream m_logFile; mutable std::mutex m_mutex; }; // Convenience macros for logging #define LOG_DEBUG(msg) Logger::getInstance().debug(msg, LoggerType::INTERNAL) #define LOG_INFO(msg) Logger::getInstance().info(msg, LoggerType::INTERNAL) #define LOG_WARNING(msg) Logger::getInstance().warning(msg, LoggerType::INTERNAL) #define LOG_ERROR(msg) Logger::getInstance().error(msg, LoggerType::INTERNAL) // HTTP-specific logging macros #define HTTP_DEBUG(msg) Logger::getInstance().debug(msg, LoggerType::HTTP) #define HTTP_INFO(msg) Logger::getInstance().info(msg, LoggerType::HTTP) #define HTTP_WARNING(msg) Logger::getInstance().warning(msg, LoggerType::HTTP) #define HTTP_ERROR(msg) Logger::getInstance().error(msg, LoggerType::HTTP) #endif // LOGGER_H