開源日志庫spdlog的使用心得
所有大型項目中都需要實現日志功能。此功能看似簡單實則不然,實現一個高速、穩定、功能完善的日志中心是每一個大型項目的必經之路。spdlog是目前Github上一款基於C/C++的開源日志庫。它有以下特點:
-
速度非常快
-
只包含頭文件
-
無需依賴第三方庫
-
支持跨平台 - Linux / Windows on 32/64 bits / Mac OS
-
支持多線程
-
可對日志文件進行循環輸出
-
可每日生成日志文件
-
支持控制台日志輸出
-
可選的異步日志
-
支持日志輸出級別
-
可自定義日志格式
實際使用下來確實比較舒服。首先spdlog不需要編譯,引入頭文件就行,用起來非常簡單。其次它的循環日志文件和異步打印日志這兩個功能也非常好用,讓整個日志功能變得非常的優雅。
最簡單的使用場景
這種場景下日志直接在控制台輸出,一般不會用這個的,比較的低級。但是可以看出spdlog的格式化輸出形式和傳統的C/C++不太相像,更偏向於Python一點。實際用起來也更簡單。
#include "spdlog/spdlog.h"
int main()
{
spdlog::info("Hello, {}!", "World");
}
單一日志文件的使用場景
my_logger作為日志的生產者可以初始化為一個全局變量。這種用法也不會常用,功能太少。
#include <iostream>
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h" // support for basic file logging
int main(int, char* [])
{
try
{
auto my_logger = spdlog::basic_logger_mt("basic_logger", "logs/basic.txt");
my_logger->info("Hello {}", "world");
}
catch (const spdlog::spdlog_ex& ex)
{
std::cout << "Log initialization failed: " << ex.what() << std::endl;
}
}
循環日志文件的使用場景
這種場景就比較常見了。首先日志不能一直不限量的增長,達到一定量必須分割為多文件;其次日志文件的數量也不能無限增長,否則日志量一大會把硬盤撐爆。循環日志文件能輕易解決以上兩個問題。
#include <iostream>
#include "spdlog/spdlog.h"
#include "spdlog/sinks/rotating_file_sink.h" // support for rotating file logging
int main(int, char* [])
{
try
{
auto file_logger = spdlog::rotating_logger_mt("file_logger", "myfilename",
1024 * 1024 * 5, 10);
file_logger->set_level(spdlog::level::debug);
while (i < 1000000)
{
file_logger->debug("Async message #{}", i);
i++;
}
}
catch (const spdlog::spdlog_ex& ex)
{
std::cout << "Log initialization failed: " << ex.what() << std::endl;
}
}
區別於單一文件,循環日志的生產者類是rotating_logger_mt。rotating_logger_mt初始化的時候需要4個參數。
- 生產者的名字,自定義即可;
- 日志文件路徑,相對和絕對均可;
- 單一文件的大小,超過了設置大小就生成一個新的文件。上面代碼中設置為5MB;
- 保留文件數量,超過數量的文件會直接刪掉以節省空間。正常使用的時候此數字大一些較好。
代碼中生成100萬條日志,數據大約是65MB。那么在根目錄下就會出現10個日志文件,后綴名由1~9。最初的3個文件則會被刪除。
異步打印日志文件
大型項目中經常有很多場景是對時間有着嚴苛要求的,此時異步調用打印日志功能就顯得十分重要了。spdlog實現異步打印日志的功能也是非常地簡單。
#include <iostream>
#include "spdlog/spdlog.h"
#include "spdlog/async.h"
#include "spdlog/sinks/rotating_file_sink.h"
int main(){
spdlog::init_thread_pool(10000, 1);
auto file_logger = spdlog::rotating_logger_mt<spdlog::async_factory>("file_logger", "mylogs", 1024 * 1024 * 5, 100);
int i = 0;
file_logger->set_level(spdlog::level::debug);
while (i < 1000000)
{
file_logger->debug("Async message #{}", i);
i++;
}
spdlog::drop_all();
return 0;
}
在初始化的時候使用異步工廠spdlog::async_factory進行初始化即可。
其他功能
spdlog除了以上功能,還可以按天分割文件,多源寫入同條日志,自定義日志格式等功能。
缺點
目前這個庫有一大缺陷就是不支持日志壓縮,要知道項目中如果打開了Debug級別的日志,日志量可能是非常恐怖的,如果分割文件的時候不能壓縮文件將是對硬盤空間的極大浪費(日志壓縮率一般在95%左右)。但是既然是開源項目,自己改源代碼也是可以的。