spdlog 日志库学习,简易封装
生活随笔
收集整理的這篇文章主要介紹了
spdlog 日志库学习,简易封装
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
spdlog wiki:https://github.com/gabime/spdlog/wiki
別人的學習筆記:https://www.cnblogs.com/oucsheep/p/8426548.html
別人的學習筆記:https://github.com/gabime/spdlog/wiki
百度搜 spdlog 封裝可以看到很多寫的差不多的單例類,我看公司遺留的代碼也是借鑒這些寫的。
最常見的是一開頭就寫上:
#ifdef _WIN32
#define __FILENAME__ (strrchr(__FILE__, '\\') ? (strrchr(__FILE__, '\\') + 1):__FILE__)
#else
#define __FILENAME__ (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1):__FILE__)
#endif
//定義一個在日志后添加 文件名 函數名 行號 的宏定義
#ifndef suffix
#define suffix(msg) std::string(msg).append(" <")\
.append(__FILENAME__).append("> <").append(__func__)\
.append("> <").append(std::to_string(__LINE__))\
.append(">").c_str()
//#define suffix(msg) std::string().append(" File:")\
// .append(__FILENAME__).append("\", Func:\"").append(__func__)\
// .append("()\", Line:\"").append(std::to_string(__LINE__)).append("\"").append(msg).c_str()
#endif
這種文件行號之類的 spdlog 本身也自帶,可以參見 SPDLOG_LOGGER_CALL 宏定義,用這個還得加上宏:
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE
不過它自帶的函數用的__FUNCTION__ 在 VS 下會顯示類名,我自定義改成了 __func__ 只保留了函數名。
代碼如下:
#pragma once
//定義宏使輸出文件名和行號
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE
#define SPDLOG_TRACE_ON
//#define SPDLOG_DEBUG_ON
#include "spdlog/spdlog.h"
#include "spdlog/sinks/easy_file_sink.h"
//#include "spdlog/sinks/daily_file_sink.h"
//spdlog 簡易封裝
//龔建波 2021-1-27 修改
//''' 示例
// Qt使用時 CONFIG += utf8_source
// INITLOG(QString("日志.log").toLocal8Bit().toStdString());
// ERRORLOG("測試下 {0} {1} {2} {3}",123,true,"測試下",QString("測試下").toStdString());
// WARNLOG("測試下 {0} {1} {2} {3}",123,true,"測試下",QString("測試下").toStdString());
// INFOLOG("測試下 {0} {1} {2} {3}",123,true,"測試下",QString("測試下").toStdString());
// DEBUGLOG("測試下 {0} {1} {2} {3}",123,true,"測試下",QString("測試下").toStdString());
// TRACELOG("測試下 {0} {1} {2} {3}",123,true,"測試下",QString("測試下").toStdString());
//'''
//spdlog講解參見博客 https://www.cnblogs.com/oucsheep/p/8426548.html
class BaseLog
{
private:
BaseLog()=default;
public:
static BaseLog* getInstance() {
static BaseLog instance;
return &instance;
}
//初始化日志,路徑使用locale編碼
//如: QString("日志.log").toLocal8Bit().toStdString()
void init(const std::string& path){
//自定義的sink
logPtr = spdlog::easy_logger_mt("easy",path,1024*1024*25);
//可以配置多個sink
//std::make_shared<spdlog::logger>
//spdlog::register_logger(logPtr); 配合 spdlog::drop_all();
//設置日志記錄級別
logPtr->set_level(spdlog::level::trace);
//設置格式
//參見文檔 https://github.com/gabime/spdlog/wiki/3.-Custom-formatting
//[%Y-%m-%d %H:%M:%S.%e] 時間
//[%l] 日志級別
//[%t] 線程
//[%s] 文件
//[%#] 行號
//[%!] 函數
//[%v] 實際文本
logPtr->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] [%t] [%s %!:%#] %v");
//設置當出發 err 或更嚴重的錯誤時立刻刷新日志到 disk
logPtr->flush_on(spdlog::level::trace);
//spdlog::flush_every(std::chrono::seconds(3));
}
auto logger() {
return logPtr;
}
private:
std::shared_ptr<spdlog::logger> logPtr;
};
#define INITLOG(path) BaseLog::getInstance()->init(path)
//參見SPDLOG_LOGGER_CALL
#define SPDLOG_BASE(logger, level, ...) (logger)->log(spdlog::source_loc{__FILE__, __LINE__, __func__}, level, __VA_ARGS__)
#define TRACELOG(...) SPDLOG_BASE(BaseLog::getInstance()->logger(), spdlog::level::trace, __VA_ARGS__)
#define DEBUGLOG(...) SPDLOG_BASE(BaseLog::getInstance()->logger(), spdlog::level::debug, __VA_ARGS__)
#define INFOLOG(...) SPDLOG_BASE(BaseLog::getInstance()->logger(), spdlog::level::info, __VA_ARGS__)
#define WARNLOG(...) SPDLOG_BASE(BaseLog::getInstance()->logger(), spdlog::level::warn, __VA_ARGS__)
#define ERRORLOG(...) SPDLOG_BASE(BaseLog::getInstance()->logger(), spdlog::level::err, __VA_ARGS__)
#define CRITICALLOG(...) SPDLOG_BASE(BaseLog::getInstance()->logger(), spdlog::level::critical, __VA_ARGS__)
再貼一個百度出來的:https://blog.csdn.net/et_endeavoring/article/details/86109121
#pragma once
#include "Util.h"
#ifdef _WIN32
#define __FILENAME__ (strrchr(__FILE__, '\\') ? (strrchr(__FILE__, '\\') + 1):__FILE__)
#else
#define __FILENAME__ (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1):__FILE__)
#endif
//定義一個在日志后添加 文件名 函數名 行號 的宏定義
#ifndef suffix
#define suffix(msg) std::string(msg).append(" <")\
.append(__FILENAME__).append("> <").append(__func__)\
.append("> <").append(std::to_string(__LINE__))\
.append(">").c_str()
//#define suffix(msg) std::string().append(" File:")\
// .append(__FILENAME__).append("\", Func:\"").append(__func__)\
// .append("()\", Line:\"").append(std::to_string(__LINE__)).append("\"").append(msg).c_str()
#endif
//在 spdlog.h 之前定義,才有效
#ifndef SPDLOG_TRACE_ON
#define SPDLOG_TRACE_ON
#endif
#ifndef SPDLOG_DEBUG_ON
#define SPDLOG_DEBUG_ON
#endif
#include <spdlog\spdlog.h>
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/basic_file_sink.h"
#include <spdlog\sinks\daily_file_sink.h>
class Logger
{
public:
static Logger& GetInstance() {
static Logger m_instance;
return m_instance;
}
auto GetLogger() { return nml_logger; }
private:
Logger() {
util::MakeSureDirExist("logs");
//設置為異步日志
//spdlog::set_async_mode(32768); // 必須為 2 的冪
std::vector<spdlog::sink_ptr> sinkList;
//#ifdef _CONSOLE
#ifdef _DEBUG
auto consoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
consoleSink->set_level(spdlog::level::debug);
//consoleSink->set_pattern("[multi_sink_example] [%^%l%$] %v");
consoleSink->set_pattern("[%m-%d %H:%M:%S.%e][%^%L%$] %v");
sinkList.push_back(consoleSink);
#endif
auto basicSink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/basicSink.txt");
basicSink->set_level(spdlog::level::debug);
basicSink->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%5l%$] %v");
sinkList.push_back(basicSink);
nml_logger = std::make_shared<spdlog::logger>("both", begin(sinkList), end(sinkList));
//register it if you need to access it globally
spdlog::register_logger(nml_logger);
// 設置日志記錄級別
#ifdef _DEBUG
nml_logger->set_level(spdlog::level::trace);
#else
nml_logger->set_level(spdlog::level::err);
#endif
//設置 logger 格式[%^%L%$]
//nml_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%5l] %v");
//nml_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%5l%$] %v");
//設置當出發 err 或更嚴重的錯誤時立刻刷新日志到 disk
nml_logger->flush_on(spdlog::level::err);
spdlog::flush_every(std::chrono::seconds(3));
}
~Logger() {
spdlog::drop_all();
}
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
private:
std::shared_ptr<spdlog::logger> nml_logger;
};
//Logger& operator<<(Logger& log, const char* s);
//Logger& operator<<(Logger& log, const std::string& s);
//#define DEBUG Logger::GetInstance()
#define LTrace(msg,...) Logger::GetInstance().GetLogger()->trace(suffix(msg),__VA_ARGS__)
//#define LDebug(msg,...) Logger::GetInstance().GetLogger()->debug(suffix(msg),__VA_ARGS__)
#define LDebug(...) Logger::GetInstance().GetLogger()->debug(__VA_ARGS__)
#define LInfo(...) Logger::GetInstance().GetLogger()->info(__VA_ARGS__)
#define LWarn(...) Logger::GetInstance().GetLogger()->warn(__VA_ARGS__)
#define LError(...) Logger::GetInstance().GetLogger()->error(__VA_ARGS__)
#define LCritical(...) Logger::GetInstance().GetLogger()->critical(__VA_ARGS__)
#define criticalif(b, ...) \
do { \
if ((b)) { \
Logger::GetInstance().GetLogger()->critical(__VA_ARGS__); \
} \
} while (0)
#ifdef WIN32
#define errcode WSAGetLastError()
#endif
總結
以上是生活随笔為你收集整理的spdlog 日志库学习,简易封装的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TCP/IP详解笔记----第一章:概述
- 下一篇: Karate-让WebService的测