【C++】spdlog--log4cxx有點笨重,試一試spdlog
spdlog是什麼
Fast C++ logging library
按照官方介紹,是一個高效能的C++日誌元件,支援跨平臺,相容 C++11。原來專案中使用的是log4cxx,我感覺稍微有點笨重,並且很久沒有更新了。
在新專案中,我只需要一款輕量級的日誌元件,能:
- 存檔案
- 按照天數切分
快速的瀏覽了spdlog,滿足我的需求,於是開搞!
spdlog快速入門
github:https://github.com/gabime/spdlog
以下內容來自spdlog的 README
編譯
$ git clone https://github.com/gabime/spdlog.git
$ cd spdlog && mkdir build && cd build
$ cmake .. && make -j
PS:使用cmake來編譯,cmake 命令會生成makefile。如果機器上沒有cmake,請先安裝一下,我的cmake3.14.5,macos 10.15,
meki-mac-pro:~ xuyc$ cmake -version
cmake version 3.14.5
CMake suite maintained and supported by Kitware (kitware.com/cmake).
使用
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"
int main()
{
spdlog::info("Welcome to spdlog!");
spdlog::error("Some error message with arg: {}", 1);
spdlog::warn("Easy padding in numbers like {:08d}", 12);
spdlog::critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
spdlog::info("Support for floats {:03.2f}", 1.23456);
spdlog::info("Positional args are {1} {0}..", "too", "supported");
spdlog::info("{:<30}", "left aligned");
spdlog::set_level(spdlog::level::debug); // Set global log level to debug
spdlog::debug("This message should be displayed..");
// change log pattern
spdlog::set_pattern("[%H:%M:%S %z] [%n] [%^---%L---%$] [thread %t] %v");
// Compile time log levels
// define SPDLOG_ACTIVE_LEVEL to desired level
SPDLOG_TRACE("Some trace message with param {}", 42);
SPDLOG_DEBUG("Some debug message");
// Set the default logger to file logger
auto file_logger = spdlog::basic_logger_mt("basic_logger", "logs/basic.txt");
spdlog::set_default_logger(file_logger);
}
官方的程式碼大概知道怎麼使用spdlog了,點個贊。但是可能會遇到一些問題,下面筆者遇到問題的記錄。
常見問題
列印行號
// 先設定日誌輸出格式
// %s:檔名,my_file.cpp
// %#:行號,123
// %!:函式名,my_func
spdlog::set_pattern("%Y-%m-%d %H:%M:%S [%l] [%t] - <%s>|<%#>|<%!>,%v");
// 使用巨集才會有行號
SPDLOG_DEBUG("Some debug message");
spdlog::info("Welcome to spdlog!");
具體見:https://github.com/gabime/spdlog/wiki/3.-Custom-formatting
推薦寫法:
#define DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__)
#define LOG(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__)
#define WARN(...) SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__)
#define ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__)
DEBUG("debug");
LOG("info");
怎麼控制檯看不到log
設定預設logger為控制檯即可
// 設定預設logger,這裡是控制檯,所以spdlog::info的內容會輸出到控制檯
auto console = spdlog::stdout_color_mt("console");
spdlog::set_default_logger(console);
官方程式碼
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
void stdout_example()
{
// create color multi threaded logger
auto console = spdlog::stdout_color_mt("console");
//auto err_logger = spdlog::stderr_color_mt("stderr");
spdlog::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name)");
}
同時輸出控制檯和檔案
- 先註冊
// 每天2:30 am 新建一個日誌檔案
auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
// 遇到warn flush日誌,防止丟失
logger->flush_on(spdlog::level::warn);
- 通過巨集來同時輸出console和檔案,注意logger名字和上面的對應。
// spd 帶行號的列印,同時輸出console和檔案
#define DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_DEBUG(spdlog::get("daily_logger"), __VA_ARGS__)
#define LOG(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_INFO(spdlog::get("daily_logger"), __VA_ARGS__)
#define WARN(...) SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_WARN(spdlog::get("daily_logger"), __VA_ARGS__)
#define ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_ERROR(spdlog::get("daily_logger"), __VA_ARGS__)
檔案按天分割
#include "spdlog/sinks/daily_file_sink.h"
void daily_example()
{
// Create a daily logger - a new file is created every day on 2:30am
auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
}
停止除錯log沒有寫檔案?
spdlog為了提高效能,降低對磁碟的寫操作,通過flush機制來一次性把日誌寫入到檔案裡面持久化。所以如果沒有恰當的配置,停止除錯或者程式崩潰的時候會有日誌丟失的問題。
定時flush到檔案:
//每三秒重新整理一次
spdlog::flush_every(std::chrono::seconds(3));
遇到error級別,立即flush到檔案:
enum level_enum
{
trace = SPDLOG_LEVEL_TRACE, // 最低
debug = SPDLOG_LEVEL_DEBUG,
info = SPDLOG_LEVEL_INFO,
warn = SPDLOG_LEVEL_WARN,
err = SPDLOG_LEVEL_ERROR,
critical = SPDLOG_LEVEL_CRITICAL, // 最高
off = SPDLOG_LEVEL_OFF,
n_levels
};
auto logger = spdlog::daily_logger_mt("daily_logger", "log/daily.txt", 2, 30);
// 遇到warn或者更高階別,比如err,critical 立即flush日誌,防止丟失
logger->flush_on(spdlog::level::warn);
完整程式碼
// spdlog
#include "spdlog/spdlog.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include <iostream>
#include <memory>
// spd 帶行號的列印,同時輸出console和檔案
#define DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_DEBUG(spdlog::get("daily_logger"), __VA_ARGS__)
#define LOG(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_INFO(spdlog::get("daily_logger"), __VA_ARGS__)
#define WARN(...) SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_WARN(spdlog::get("daily_logger"), __VA_ARGS__)
#define ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__);SPDLOG_LOGGER_ERROR(spdlog::get("daily_logger"), __VA_ARGS__)
int main(int argc, char *argv[]) {
// 按檔案大小
//auto file_logger = spdlog::rotating_logger_mt("file_log", "log/log.log", 1024 * 1024 * 100, 3);
// 每天2:30 am 新建一個日誌檔案
auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
// 遇到warn flush日誌,防止丟失
logger->flush_on(spdlog::level::warn);
//每三秒重新整理一次
spdlog::flush_every(std::chrono::seconds(3));
// Set the default logger to file logger
auto console = spdlog::stdout_color_mt("console");
spdlog::set_default_logger(console);
spdlog::set_level(spdlog::level::debug); // Set global log level to debug
// change log pattern
// %s:檔名
// %#:行號
// %!:函式名
spdlog::set_pattern("%Y-%m-%d %H:%M:%S [%l] [%t] - <%s>|<%#>|<%!>,%v");
LOG("test info");
ERROR("test error");
// Release and close all loggers
spdlog::drop_all();
}
控制檯輸出
/Users/xuyc/repo/sd_linux/cmake-build-debug/sd_linux
[2020-04-30 16:14:41.816] [console] [info] [main.cpp:608] test info
[2020-04-30 16:14:41.816] [console] [error] [main.cpp:609] test error
Process finished with exit code 0
檔案
附錄
網上說只需要標頭檔案即可,不過我還是連結了。。。
CMakeList.txt
cmake_minimum_required(VERSION 3.15)
project(sd_linux)
set(CMAKE_CXX_STANDARD 14)
AUX_SOURCE_DIRECTORY(./ SRC_LIST)
AUX_SOURCE_DIRECTORY(./jsoncpp SRC_LIST)
// 包含spdlog的標頭檔案
INCLUDE_DIRECTORIES(./jsoncpp ./spdlog/include)
// 包含spdlog的動態庫目錄
LINK_DIRECTORIES(./ ./spdlog/build)
add_executable(sd_linux ${SRC_LIST})
// 連結spdlog動態庫
TARGET_LINK_LIBRARIES(sd_linux curl iconv spdlog)
關於
推薦下自己的開源IM,純Golang編寫:
CoffeeChat:
https://github.com/xmcy0011/CoffeeChat
opensource im with server(go) and client(flutter+swift)
參考了TeamTalk、瓜子IM等知名專案,包含服務端(go)和客戶端(flutter),單聊和機器人(小微、圖靈、思知)聊天功能已完成,目前正在研發群聊功能,歡迎對golang和跨平臺開發flutter技術感興趣的小夥伴Star加關注。
原文連結:https://blog.csdn.net/xmcy001122/article/details/105665732
相關文章
- Windows有點膩了?不如試試Ubuntu.WindowsUbuntu
- 有關oracle external table的一點測試。Oracle
- 有關lock的一點測試總結!
- OTT 方面的測試,有沒有熱 做過系統一點的測試,求指教。
- 有關測試開發的點在哪
- 軟體測試的痛點有哪些?
- cursor express的一點測試!Express
- C/C++字串筆試知識點及例項C++字串筆試
- c++筆試題C++筆試
- 測試流程與測試人員配置的一點感想
- 軟體安全測試有哪些測試要點?軟體安全測試報告價格是多少?測試報告
- mv(materialized view)的一點測試ZedView
- Index Joins的一點測試!Index
- C++學習筆記,知識點+程式碼測試C++筆記
- 面試C++試題 (轉)面試
- c++效能測試工具:google benchmark進階(一)C++Go
- redis測試點Redis
- 軟體測試流程的一點感悟
- index clusterring cluster的一點測試!Index
- C/C++期末考試複習---知識點+習題C++
- 軟體安全性測試要點有哪些?常用軟體安全測試工具分享
- 開發做測試是不是有點可惜,大才小用了?
- 效能測試有哪些指標需要測試?指標
- C/C++求職寶典21個重點筆記(常考筆試面試點)C++求職筆記筆試面試
- 軟體穩定性測試的測試點
- 智慧城市試點90個--智慧工廠試點100個
- 許可權傳遞的一點測試!
- RHCE考試的一些知識點
- 測試的思考點
- 軟體效能測試有哪些測試過程?
- 騰訊研發類筆試面試試題及答案(C++方向)筆試面試C++
- 效能測試、負載測試、壓力測試有什麼區別?負載
- 對於一個 APP 測試和 web 測試應該有哪些成長呢!APPWeb
- 【轉】C++ 筆試面試題目C++筆試面試題
- C++霧中風景16:std::make_index_sequence, 來試一試新的黑魔法吧C++Index
- 最全APP測試思想及流程要點,高薪測試人員一定要看!APP高薪
- (一)效能測試(壓力測試、負載測試)負載
- 軟體安全測試有哪些方法?在哪裡測試?