目录
说明
基于spdlog库做了一点封装,该类支持以下操作
- 自定义日志路径 (支持相对路径、绝对路径,支持路径包括目录)
- 支持日志输出模式 (同步、异步)
- 支持日志输出等级控制 (指定输出什么等级以上的消息)
- 支持日志输出位置 (控制台、文件、控制台+文件)
该文章只是简单的单日志文件处理,后续的优化都在gitee上,详细内容请跳转该地址:log: 基于C++ spdlog日志库的二次封装 - Gitee.com
日志输出实例图片
类使用示例
#pragma once
#include "Hlog.h"
int main()
{
Hlog log;
log.Init(".log/test.log", 1024*1024*1000, 10,
Hlog::SYNC, Hlog::CONSOLE_AND_FILE, Hlog::LEVEL_WARN);
LOG_TRACE("test {}", 1);
LOG_DEBUG("test {:.2f}", 1.0000);
LOG_INFO("test {}", 1.23456789);
LOG_WARN("test {}", 'A');
LOG_ERROR("test {}", "ABC");
LOG_CRITI("test {}", std::string("abc"));
return 0;
}
封装类实现
.h
#pragma once
#include "spdlog/spdlog.h"
#include "spdlog/async_logger.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/details/thread_pool.h"
#include "spdlog/details/thread_pool-inl.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/async.h" //support for async logging
//日志名称
#define LOG_NAME "multi_sink"
//封装宏,没有该宏无法输出文件名、行号等信息
#define LOG_TRACE(...) SPDLOG_LOGGER_CALL(spdlog::get(LOG_NAME), spdlog::level::trace, __VA_ARGS__)
#define LOG_DEBUG(...) SPDLOG_LOGGER_CALL(spdlog::get(LOG_NAME), spdlog::level::debug, __VA_ARGS__)
#define LOG_INFO(...) SPDLOG_LOGGER_CALL(spdlog::get(LOG_NAME), spdlog::level::info, __VA_ARGS__)
#define LOG_WARN(...) SPDLOG_LOGGER_CALL(spdlog::get(LOG_NAME), spdlog::level::warn, __VA_ARGS__)
#define LOG_ERROR(...) SPDLOG_LOGGER_CALL(spdlog::get(LOG_NAME), spdlog::level::err, __VA_ARGS__)
#define LOG_CRITI(...) SPDLOG_LOGGER_CALL(spdlog::get(LOG_NAME), spdlog::level::critical, __VA_ARGS__)
class Hlog
{
public:
//日志输出位置
enum OutPosition {
CONSOLE = 0x01, //控制台
FILE = 0X02, //文件
CONSOLE_AND_FILE = 0x03, //控制台+文件
};
enum OutMode {
SYNC, //同步模式
ASYNC, //异步模式
};
//日志输出等级
enum OutLevel {
LEVEL_TRACE = 0,
LEVEL_DEBUG = 1,
LEVEL_INFO = 2,
LEVEL_WARN = 3,
LEVEL_ERROR = 4,
LEVEL_CRITI = 5,
LEVEL_OFF = 6,
};
public:
Hlog();
~Hlog();
/* func: 初始化日志通道
* @para[in] nFileName : 日志存储路径 (支持相对路径和绝对路径)
* @para[in] nMaxFileSize : 日志文件最大存储大小 (默认1024*1024*10)
* @para[in] nMaxFile : 最多存储多少个日志文件 (默认10,超过最大值则循环覆盖)
* @para[in] outMode : 日志输出模式 (同步、异步)
* @para[in] outPos : 日志输出位置 (控制台、文件、控制台+文件)
* @para[in] outLevel : 日志输出等级 (只输出>=等级的日志消息)
*/
bool Init(const char* nFileName, const int nMaxFileSize = 1024 * 1024 * 10, const int nMaxFile = 10,
const OutMode outMode = SYNC, const OutPosition outPos = CONSOLE_AND_FILE, const OutLevel outLevel = LEVEL_TRACE);
void UnInit();
private:
public:
std::shared_ptr<spdlog::logger> m_pLogger;
bool m_bInit;
};
.cpp
#include "Hlog.h"
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
Hlog::Hlog()
:m_bInit(false)
{
}
Hlog::~Hlog()
{
if (m_bInit)
{
this->UnInit();
}
}
bool Hlog::Init(const char* nFileName, const int nMaxFileSize, const int nMaxFile,
const OutMode outMode, const OutPosition outPos, const OutLevel outLevel)
{
if (m_bInit)
{
printf("It's already initialized\n");
return false;
}
m_bInit = true;
try
{
const char* pFormat = "[%Y-%m-%d %H:%M:%S.%e] <thread %t> [%^%l%$]\n[%@,%!]\n%v\n";
//sink容器
std::vector<spdlog::sink_ptr> vecSink;
//控制台
if (outPos & CONSOLE)
{
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
//console_sink->set_level(spdlog::level::trace);
console_sink->set_pattern(pFormat);
vecSink.push_back(console_sink);
}
//文件
if (outPos & FILE)
{
auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(nFileName, nMaxFileSize, nMaxFile);
//file_sink->set_level(spdlog::level::trace);
file_sink->set_pattern(pFormat);
vecSink.push_back(file_sink);
}
//设置logger使用多个sink
if (outMode == ASYNC)//异步
{
spdlog::init_thread_pool(102400, 1);
auto tp = spdlog::thread_pool();
m_pLogger = std::make_shared<spdlog::async_logger>(LOG_NAME, begin(vecSink), end(vecSink), tp, spdlog::async_overflow_policy::block);
}
else//同步
{
m_pLogger = std::make_shared<spdlog::logger>(LOG_NAME, begin(vecSink), end(vecSink));
}
m_pLogger->set_level((spdlog::level::level_enum)outLevel);
//遇到warn级别,立即flush到文件
m_pLogger->flush_on(spdlog::level::warn);
//定时flush到文件,每三秒刷新一次
spdlog::flush_every(std::chrono::seconds(3));
spdlog::register_logger(m_pLogger);
}
catch(const spdlog::spdlog_ex& ex)
{
std::cout << "Log initialization failed: " << ex.what() << std::endl;
return false;
}
return true;
}
void Hlog::UnInit()
{
spdlog::drop_all();
spdlog::shutdown();
}