/* */ #ifndef _D_LOGGER_H_ #define _D_LOGGER_H_ #include "common.h" #include #include #include #include namespace aria2 { class Exception; class Logger { public: enum LEVEL { A2_DEBUG = 1 << 0, A2_INFO = 1 << 1, A2_NOTICE = 1 << 2, A2_WARN = 1 << 3, A2_ERROR = 1 << 4, }; static const std::string DEBUG_LABEL; static const std::string NOTICE_LABEL; static const std::string WARN_LABEL; static const std::string ERROR_LABEL; static const std::string INFO_LABEL; private: LEVEL _logLevel; std::ofstream _file; int _stdoutField; inline bool levelEnabled(LEVEL level) { return (level >= _logLevel && _file.is_open()) || _stdoutField&level; } protected: virtual void writeLog (std::ostream& o, LEVEL logLevel, const std::string& logLevelLabel, const char* msg, va_list ap) = 0; virtual void writeStackTrace (std::ostream& o, LEVEL logLevel, const std::string& logLevelLabel, const Exception& ex) = 0; public: Logger(); virtual ~Logger(); #define WRITE_LOG(LEVEL, LEVEL_LABEL, MSG) \ if(LEVEL >= _logLevel && _file.is_open()) { \ va_list ap; \ va_start(ap, MSG); \ writeLog(_file, LEVEL, LEVEL_LABEL, MSG, ap); \ va_end(ap); \ _file << std::flush; \ } \ if(_stdoutField&LEVEL) { \ std::cout << "\n"; \ va_list ap; \ va_start(ap, MSG); \ writeLog(std::cout, LEVEL, LEVEL_LABEL, MSG, ap); \ va_end(ap); \ std::cout << std::flush; \ } \ #define WRITE_LOG_EX(LEVEL, LEVEL_LABEL, MSG, EX) \ if(LEVEL >= _logLevel && _file.is_open()) { \ va_list ap; \ va_start(ap, EX); \ writeLog(_file, LEVEL, LEVEL_LABEL, MSG, ap); \ va_end(ap); \ writeStackTrace(_file, LEVEL, LEVEL_LABEL, EX); \ _file << std::flush; \ } \ if(_stdoutField&LEVEL) { \ std::cout << "\n"; \ va_list ap; \ va_start(ap, EX); \ writeLog(std::cout, LEVEL, LEVEL_LABEL, MSG, ap); \ va_end(ap); \ writeStackTrace(std::cout, LEVEL, LEVEL_LABEL, EX); \ std::cout << std::flush; \ } \ void debug(const char* msg, ...) { WRITE_LOG(A2_DEBUG, DEBUG_LABEL, msg); } void debug(const char* msg, const Exception& ex, ...) { WRITE_LOG_EX(A2_DEBUG, DEBUG_LABEL, msg, ex); } void info(const char* msg, ...) { WRITE_LOG(A2_INFO, INFO_LABEL, msg); } void info(const char* msg, const Exception& ex, ...) { WRITE_LOG_EX(A2_INFO, INFO_LABEL, msg, ex); } void notice(const char* msg, ...) { WRITE_LOG(A2_NOTICE, NOTICE_LABEL, msg); } void notice(const char* msg, const Exception& ex, ...) { WRITE_LOG_EX(A2_NOTICE, NOTICE_LABEL, msg, ex); } void warn(const char* msg, ...) { WRITE_LOG(A2_WARN, WARN_LABEL, msg); } void warn(const char* msg, const Exception& ex, ...) { WRITE_LOG_EX(A2_WARN, WARN_LABEL, msg, ex); } void error(const char* msg, ...) { WRITE_LOG(A2_ERROR, ERROR_LABEL, msg); } void error(const char* msg, const Exception& ex, ...) { WRITE_LOG_EX(A2_ERROR, ERROR_LABEL, msg, ex); } void openFile(const std::string& filename); void closeFile(); void setLogLevel(LEVEL level) { _logLevel = level; } void setStdoutLogLevel(Logger::LEVEL level, bool enabled) { if(enabled) { _stdoutField |= level; } else { _stdoutField &= ~level; } } // Returns true if this logger actually writes debug log message to // either file or stdout. bool debug() { return levelEnabled(A2_DEBUG); } bool info() { return levelEnabled(A2_INFO); } }; } // namespace aria2 #endif // _D_LOGGER_H_