spdlog使用说明: https://github.com/gabime/spdlog/wiki
常见的头开始部分
#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
1. 头文件logger.h
// logger.h
#ifndef LOGGER_H
#define LOGGER_H
#include "spdlog/spdlog.h"
#include "spdlog/sinks/rotating_file_sink.h"
// 日志的配置项
struct LogConfig {
std::string level;
std::string path;
int64_t size;
int count;
};
// 日志的单例模式
class Logger {
public:
static Logger* getInstance() {
static Logger instance;
return &instance;
}
//c++14返回值可设置为auto
std::shared_ptr<spdlog::logger> getLogger() {
return loggerPtr;
}
void Init(const LogConfig& conf);
std::string GetLogLevel();
void SetLogLevel(const std::string& level);
private:
Logger() = default;
std::shared_ptr<spdlog::logger> loggerPtr;
};
// 日志相关操作的宏封装
#define INITLOG(conf) Logger::getInstance()->Init(conf)
#define GETLOGLEVEL() Logger::getInstance()->GetLogLevel()
#define SETLOGLEVEL(level) Logger::getInstance()->SetLogLevel(level)
#define BASELOG(logger, level, ...) (logger)->log(spdlog::source_loc{__FILE__, __LINE__, __func__}, level, __VA_ARGS__)
#define TRACELOG(...) BASELOG(Logger::getInstance()->getLogger(), spdlog::level::trace, __VA_ARGS__)
#define DEBUGLOG(...) BASELOG(Logger::getInstance()->getLogger(), spdlog::level::debug, __VA_ARGS__)
#define INFOLOG(...) BASELOG(Logger::getInstance()->getLogger(), spdlog::level::info, __VA_ARGS__)
#define WARNLOG(...) BASELOG(Logger::getInstance()->getLogger(), spdlog::level::warn, __VA_ARGS__)
#define ERRORLOG(...) BASELOG(Logger::getInstance()->getLogger(), spdlog::level::err, __VA_ARGS__)
#define CRITICALLOG(...) BASELOG(Logger::getInstance()->getLogger(), spdlog::level::critical, __VA_ARGS__)
#endif // LOGGER_H
2. 实现文件logger.cpp
// logger.cpp
#include "logger.h"
void Logger::Init(const LogConfig& conf) {
//自定义的sink
loggerPtr = spdlog::rotating_logger_mt("base_logger", conf.path.c_str(), conf.size, conf.count);
//设置格式
//参见文档 https://github.com/gabime/spdlog/wiki/3.-Custom-formatting
//[%Y-%m-%d %H:%M:%S.%e] 时间
//[%l] 日志级别
//[%t] 线程
//[%s] 文件
//[%#] 行号
//[%!] 函数
//[%v] 实际文本
loggerPtr->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] [thread %t] [%s %!:%#] %v");
// 设置日志级别
loggerPtr->set_level(spdlog::level::from_str(conf.level));
// 设置刷新日志的日志级别,当出现level或更高级别日志时,立刻刷新日志到 disk
loggerPtr->flush_on(spdlog::level::from_str(conf.level));
}
/*
* trace 0
* debug 1
* info 2
* warn 3
* error 4
* critical 5
* off 6 (not use)
*/
std::string Logger::GetLogLevel() {
auto level = loggerPtr->level();
return spdlog::level::to_string_view(level).data();
}
void Logger::SetLogLevel(const std::string& log_level) {
auto level = spdlog::level::from_str(log_level);
if (level == spdlog::level::off) {
WARNLOG("Given invalid log level {}", log_level);
} else {
loggerPtr->set_level(level);
loggerPtr->flush_on(level);
}
}
3. 测试文件logger_test.cpp
#include "logger.h"
int main()
{
// 定义日志配置项
LogConfig conf = {
.level = "trace",
.path = "logger_test.log",
.size = 5 * 1024 * 1024,
.count = 10,
};
INITLOG(conf);
// 日志初始级别为trace
TRACELOG("current log level is {}", GETLOGLEVEL());
TRACELOG("this is trace log");
DEBUGLOG("this is debug log");
INFOLOG("this is info log");
WARNLOG("this is warning log");
ERRORLOG("this is a error log");
CRITICALLOG("this is critical log");
// 改为warning级别后,trace、debug、info级别日志不会输出了
SETLOGLEVEL("warn");
WARNLOG("after set log level to warning");
TRACELOG("this is trace log");
DEBUGLOG("this is debug log");
INFOLOG("this is info log");
WARNLOG("this is warning log");
ERRORLOG("this is a error log");
CRITICALLOG("this is critical log");
return 0;
}
4. 测试结果
# 编译
g++ -std=c++11 -g logger_test.cpp logger.cpp -o logger_test
# 运行
./logger_test
# 查看结果
cat logger_test.log
[2023-01-15 06:40:21.447] [trace] [thread 1988] [logger_test.cpp main:16] current log level is trace
[2023-01-15 06:40:21.447] [trace] [thread 1988] [logger_test.cpp main:17] this is trace log
[2023-01-15 06:40:21.447] [debug] [thread 1988] [logger_test.cpp main:18] this is debug log
[2023-01-15 06:40:21.447] [info] [thread 1988] [logger_test.cpp main:19] this is info log
[2023-01-15 06:40:21.447] [warning] [thread 1988] [logger_test.cpp main:20] this is warning log
[2023-01-15 06:40:21.447] [error] [thread 1988] [logger_test.cpp main:21] this is a error log
[2023-01-15 06:40:21.447] [critical] [thread 1988] [logger_test.cpp main:22] this is critical log
[2023-01-15 06:40:21.447] [warning] [thread 1988] [logger_test.cpp main:25] after set log level to warning
# 改为warning级别后,trace、debug、info级别日志不会输出了
[2023-01-15 06:40:21.447] [warning] [thread 1988] [logger_test.cpp main:29] this is warning log
[2023-01-15 06:40:21.447] [error] [thread 1988] [logger_test.cpp main:30] this is a error log
[2023-01-15 06:40:21.447] [critical] [thread 1988] [logger_test.cpp main:31] this is critical log