spdLog的使用

以下爲收集到或者個人測試的內容,侵權刪

一.優點

  • 非常快

    使用自帶的例子測試寫log,利用 次數/時鐘週期 衡量結果
    *******************************************************************************
    Single thread, 1,000,000 iterations
    *******************************************************************************
    rotating_st...        1,464,366/sec
    daily_st...           1,377,742/sec
    null_st...            1,621,649/sec
    *******************************************************************************
    10 threads sharing same logger, 1,000,000 iterations
    *******************************************************************************
    rotating_mt...        1,165,635/sec
    daily_mt...           1,151,680/sec
    null_mt...            1,512,478/sec
    *******************************************************************************
    async logging.. 10 threads sharing same logger, 1,000,000 iterations
    *******************************************************************************
    as...                 3,901,457/sec
    as...                 6,977,551/sec
    as...                 7,005,095/sec


  • 只包含頭文件
     (spdlog/spdlog.h ---> spdlog , spdlog/fmt/bundled/format.h ---> pattern_formatter)
  • 無需依賴第三方庫
  • 支持跨平臺 - Linux / Windows on 32/64 bits
  • 支持多線程

    單線程和多線程主要在鎖的定義上不一樣
    typedefrotating_file_sink<std::mutex> rotating_file_sink_mt;
    typedefrotating_file_sink<details::null_mutex>rotating_file_sink_st;
    其中 details::null_mutex 定義爲:
    structnull_mutex
    {
        voidlock() {}
        voidunlock() {}
        booltry_lock()
        {
            returntrue;
        }
    };


  • 可對日誌文件進行循環輸出
     (指的是可以用 rotating_file_sink結構在 log_1,log_2,log_3 等幾個文件中循環迭代,在不產生新的文件的情況下更新後面的文件)

    // Rotate files:
    // log.txt -> log.1.txt
    // log.1.txt -> log2.txt
    // log.2.txt -> log3.txt
    // log.3.txt -> delete


  • 可每日生成日誌文件
    daily_file_sink 每天定時產生文件日誌
  • 支持控制檯日誌輸出
  • 可選的異步日誌
  • 支持日誌輸出級別
  • 可自定義日誌格式

二.基本使用

1.直接打印日誌到console

auto console1 = spd::stdout_logger_mt("console1");
console1->error("Some error message with arg{}..", 1);
 
//console2 的module 名字不可以和以前的重複,創建的日誌名字爲 basic_log
auto console2 = spd::basic_logger_mt("basic_logger","./basic_log");
console2->info("Some log message");
 
//通過module名字獲取到對應的log指針
spd::get("console2")->info("get console by name");
 
//設置日誌等級
spd::set_level(spd::level::info);//Set global log level to info
console1->debug("This message shold not be displayed!");
console1->set_level(spd::level::debug);// Set specific logger's log level
console1->debug("This message shold be displayed..");


2.每天更新一個log文件(帶秒數)

//創建文件名類似於: daily_log_2018-01-17_10-27.txt,如果程序不退出的話,就是每天2:30 am創建新的文件       
auto console3 =  spd::daily_logger_mt("daily_logger","./daily_log", 2, 30);
console3->flush_on(spd::level::debug);
console3->info("test daily info");
console3->error("test daily error")

        如果想在文件名裏只關心天數,可以使用這個,這樣的好處是,同一天多次運行一個程序,可以把log寫到同一個文件裏面去,測試了不會覆蓋以前的內容

//創建文件名類似於: log_2018-01-17.txt
typedefspdlog::sinks::daily_file_sink<std::mutex, spdlog::sinks::dateonly_daily_file_name_calculator> dateonly_daily_file_sink_mt;
auto m_logger = spdlog::create<dateonly_daily_file_sink_mt>("logger","log","txt", 0, 0);
m_logger->info("test daily info");
m_logger->error("test daily error");

3.日誌太多的時候,當前文件重命名_1,_2,_3.再寫新的文件

//日誌文件名爲
//-rw-rw-r-- 1 ski ski    962 Jan 17 10:48 mylogfile_log.1.txt
//-rw-rw-r-- 1 ski ski    962 Jan 17 10:48 mylogfile_log.2.txt
//-rw-rw-r-- 1 ski ski    962 Jan 17 10:48 mylogfile_log.3.txt
//-rw-rw-r-- 1 ski ski    370 Jan 17 10:48 mylogfile_log.txt
 
auto rotating_logger = spd::rotating_logger_mt("rotate_log","./mylogfile_log", 1024, 3);
for (int i = 0; i < 1000; ++i)
    rotating_logger->info("{} * {} equals {:>10}", i, i, i*i);

4.flush_on命令

//遇到錯誤及以上級別會立馬將緩存的buffer寫到文件中,底層調用是std::fflush(_fd)
m_logger->flush_on(spd::level::err);

5.關閉所有的log handler

// Release and close all loggers 把所有的log對象智能指針放置到unordered_map中去,然後調用clear函數
spdlog::drop_all();


 三.源碼閱讀

spdlog支持多線程的,想看看其中是怎麼控制同步的,實現多線程的一個接口:
auto rotating_logger = spd::rotating_logger_mt("some_logger_name", "logs/rotating.txt", 1048576 * 5, 3);
點進去:
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files)
{
    return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files);
}
繼續:
typedef rotating_file_sink<std::mutex> rotating_file_sink_mt;
typedef rotating_file_sink<details::null_mutex>rotating_file_sink_st;
所有的sinks類都是繼承sinks類的,這裏是從rotating_file_sink->base_sink->sink繼承而來的。
template<class Mutex>
class rotating_file_sink SPDLOG_FINAL : public base_sink < Mutex >
看看base_sinks類中的兩個關鍵log函數:
template<class Mutex>
class base_sink:public sink
{
    void log(const details::log_msg& msg) SPDLOG_FINAL override
    {
        std::lock_guard<Mutex> lock(_mutex);
        _sink_it(msg);
    }
    void flush() SPDLOG_FINAL override
    {
        std::lock_guard<Mutex> lock(_mutex);
        _flush();
    }
在這裏是根據鎖的類型不同而實現多線程和單線程的區別,多線程的鎖可以使用正常的鎖機制來使用,那麼,單線程的使用呢? 開始查看details::null_mutex的定義:
struct null_mutex
{
    void lock() {}
    void unlock() {}
    bool try_lock()
    {
        return true;
    }
};
其實,他是使用了一個類去模擬鎖的函數,但是裏面什麼也不做,這樣就可以與多線程情況下使用同樣的代碼了,提升了代碼效率。值得借鑑


其他:

參考網址:

1.spdLog官網

2.spdLog源碼閱讀

 主要包括三頁內容:

        sink介紹(base_sink, rotating_file_sink,另外還有 daily_file_sink)

        sink創建和使用(稍微介紹了下單例模式)

        log_msg的原理介紹(緩衝區存儲日誌內容)

3.spdLog使用example

        這是spdLog自帶的一個example,教你如何使用sink去寫log

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章