0. spdlog簡單介紹
spdlog 是一個快速的 C++ 日志庫,只包含頭文件,兼容 C++11。項目地址
特性:
- 非常快
- 只包含頭文件
- 無需依賴第三方庫
- 支持跨平台 - Linux / Windows on 32/64 bits
- 支持多線程
- 可對日志文件進行循環輸出
- 可每日生成日志文件
- 支持控制台日志輸出
- 可選的異步日志
- 支持日志輸出級別
- 可自定義日志格式
(上述內容來源於 開源中國關於spdlog的介紹)
1. sinks
在spdlog中,sink指向實際的輸出目標,例如
- stdout
- syslog(linux系統日志)
- ostream
- file
- ...
代碼路徑: spdlog-master/include/spdlog/sinks
1.1 sink
class sink
{
public:
sink()
{
_level = level::trace;
}
virtual ~sink() {}
virtual void log(const details::log_msg& msg) = 0;
virtual void flush() = 0;
bool should_log(level::level_enum msg_level) const;
void set_level(level::level_enum log_level);
level::level_enum level() const;
private:
level_t _level;
};
sink類的兩個純虛函數 log flush 是子類需要實現的接口。
1.2 base_sink
沒啥好說的直接上代碼,這里僅列出主要內容。
template<class Mutex>
class base_sink:public sink
{
public:
//.....
void log(const details::log_msg& msg) override
{
std::lock_guard<Mutex> lock(_mutex);
_sink_it(msg);
}
protected:
virtual void _sink_it(const details::log_msg& msg) = 0;
Mutex _mutex;
};
模板類**base_sink繼承sink,同時實現了log接口,通過Mutex決定類是工作在單線程
還是多線程下。而子類通過實現接口_sink_it輸出日志。
在spdlog中,如果在多線程中base_sink形式如下:
base_sink<std::mutex>;
單線程:
base_sink<spdlog::details::null_mutex>;
而null_mutex什么都不做。
1.3 rotating_file_sink
通過文件饒接這個例子看下在spdlog中具體的sink是怎么實現的。
template<class Mutex>
class rotating_file_sink : public base_sink < Mutex >
{
public:
//......
protected:
void _sink_it(const details::log_msg& msg) override
{
_current_size += msg.formatted.size();
if (_current_size > _max_size)
{
_rotate();
_current_size = msg.formatted.size();
}
_file_helper.write(msg);
}
private:
//......
void _rotate()
{
for (auto i = _max_files; i > 0; --i)
{
// 修改文件名,轉儲文件
//......
}
//......
};
typedef rotating_file_sink<std::mutex> rotating_file_sink_mt;
typedef rotating_file_sink<details::null_mutex>rotating_file_sink_st;
_sink_it實現了在文件超過限制后通過_rotate轉儲文件,同時使用文件進行輸出。輸出的對象是msg(
實際的日志內容)。
代碼的最后兩行分別定義了rotating_file_sink_mt和rotating_file_sink_st。前者使用在多線程中,
后者使用在單線程。其中的區別在1.2中已經說明。