让spdlog兼容printf风格的函数

34 篇文章 0 订阅

最早使用过log4cpp,后来项目需要尽量少依赖外部so,并且支持跨平台,源码越少越好;

当时使用log4z,并且对性能做了一个简单的测试,但是最近使用中发现:日志量比较大时候,内存占用波动比较大,原因是其内部使用了8k大小的内存块,存放了200个空闲缓冲,另外如果来不及写盘,链表中的数据也会占用内存,所以简单的测试情况下,内存波动比较大。所以决定放弃了。

今天测试了spdlog,总体速度还可以,普通的云机器,能实现20万条的写入(100-200字节)而且内存波动很小,这个很喜人;

但是旧的代码使用了printf格式的日志,

风格是这样的:

LOGFMTD("debug() handle=%lld, time=%lld ", 1LL, getnSecNow());
LOGFMTE("error() handle=%lld, time=%lld ", 1LL, getnSecNow());
LOGFMTW("test warning: %s ", "it is a warn!!!");
		

为了减少更改,这里做了一个封装与嫁接:

std::shared_ptr<spdlog::logger> logger = nullptr;

#define MSG_BUF_LEN  20
#define  LOGFMTW(...) { if (logger->level() <= SPDLOG_LEVEL_WARN){  \
char buffer[MSG_BUF_LEN]; int len = snprintf(buffer, MSG_BUF_LEN, __VA_ARGS__); \
if (len < MSG_BUF_LEN) logger->warn(buffer);\
else { char * buf = new char[len + 2]; snprintf(buf, len + 2, __VA_ARGS__); logger->warn(buf);delete[] buf;} } }

#define  LOGFMTD(...) { if (logger->level() <= SPDLOG_LEVEL_DEBUG) { \
char buffer[MSG_BUF_LEN]; int len = snprintf(buffer, MSG_BUF_LEN, __VA_ARGS__); \
if (len < MSG_BUF_LEN) logger->debug(buffer);\
else { char * buf = new char[len + 2]; snprintf(buf, len + 2, __VA_ARGS__); logger->debug(buf);delete[] buf;} } }

#define  LOGFMTE(...) { if (logger->level() <= SPDLOG_LEVEL_ERROR) { \
char buffer[MSG_BUF_LEN]; int len = snprintf(buffer, MSG_BUF_LEN, __VA_ARGS__); \
if (len < MSG_BUF_LEN) logger->error(buffer);\
else { char * buf = new char[len + 2]; snprintf(buf, len + 2, __VA_ARGS__); logger->error(buf);delete[] buf;} } }

基本原理:

1)在栈上开辟4k内存,用传统方式格式化,如果不够了,则新开辟空间,并释放,具体大小根据项目情况估算;

2)使用前初始化logger;

示例如下;

// 100Mb
	auto max_size = 1024 * 1024 * 100;
	auto max_files = 20;

	// spdlog::color_mode::automatic
	auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
	console_sink->set_level(spdlog::level::warn);
	console_sink->set_pattern("[apm] [%^%l%$] %v");

	auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>("logs/cpp-agent.log", max_size, max_files);
	file_sink->set_level(spdlog::level::debug);

	std::vector<spdlog::sink_ptr> sinks;
	sinks.push_back(console_sink);
	sinks.push_back(file_sink);
	logger = std::make_shared<spdlog::logger>("apm", sinks.begin(), sinks.end());


	//logger = spdlog::logger("apm", { console_sink, file_sink });
	
	logger->set_level(spdlog::level::err);
	logger->flush_on(spdlog::level::err);

最后,可以使用valgrind测试一下内存使用情况;

valgrind --leak-check=full  --show-reachable=yes  --log-file=a.log ./testlog 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值