boost log -- 使用心得和碰到的那些坑(二)
阿新 • • 發佈:2018-12-25
前一篇文章boost log – 使用心得和碰到的那些坑(一) 寫了如何使用boost;;log, 這篇文章主要寫寫怎樣用boost;;log構建一個工程,目的就是讓使用者使用時忘掉log細節。
專案依賴
boost c++11 cmake
設計
為了以後擴充套件方便,將log設計成介面。 介面提供基本的log功能:
class logger_iface { public: public: logger_iface(void)= default; virtual ~logger_iface(void) = default; logger_iface(const logger_iface &) = default; logger_iface &operator=(const logger_iface &) = default; public: virtual void init() = 0; virtual void set_log_level(log_level level) = 0; virtual void debug_log(const std::string &msg, const std::string &file, std::size_t line) = 0; virtual void info_log(const std::string &msg, const std::string &file, std::size_t line) = 0; virtual void warn_log(const std::string &msg, const std::string &file, std::size_t line) = 0; virtual void error_log(const std::string &msg, const std::string &file, std::size_t line) = 0; virtual void critical_log(const std::string &msg, const std::string &file, std::size_t line) = 0; };
boost logger 繼承這個類。
前文已經提到了,boost logger 需要一個log core 一個sink,同時使用async backend。所以boost logger實現介面的同時加入這兩個成員變數。
boost::shared_ptr<sink_t> _sink;
boost::log::sources::severity_logger_mt<log_level> lg;
利用前文所寫的實現這幾個函式,需要注意的是 log level其實就是設定boost;;log的 filter
void boost_logger::set_log_level(log_level level) { m_level = level; if (_sink) { _sink->set_filter(expr::attr<log_level>("Severity") >= m_level); } }
現在class功能都已經實現,如何使用呢?我們需要的就是__LOG(level, msg)
這樣簡單的API。這需要有個全域性的例項。
還有一個要考慮的是, boost;;logger沒有提供檔案及檔案行號資訊。
解決這個問題, 我們有個巨集定義:
#define __LOG(level, msg) \ \ { \ tostringstream var; \ var << "[fuction:" << __func__ << "] " << msg; \ level(var.str(), __FILE__, __LINE__); \ } #else #define __LOG(level, msg) #endif /* __LOGGING_ENABLED */
其實level是一個函式,msg提供了像std;;cout一樣的用法。
下面我們看看level是怎麼實現的:
void debug(const std::string &msg, const std::string &file, std::size_t line)
{
if (active_logger)
active_logger->debug_log(msg, file, line);
}
active_logger是一個全域性的instance。
std::unique_ptr<logger_iface> active_logger(new boost_logger(log_level::error_level)); //nullptr;