C++日志库spdlog

C++日志库spdlog

使用方法

spdlog是基于C++ 11的日志组件,它非常轻量,使用时你仅仅需要引入头文件就可以了。

spdlog下载链接
或使用命令下载

wget https://github.com/gabime/spdlog

下载完成后,将includ/spdlog目录单独拷贝到自己的工程目录,g++编译文件头路径添加include/spdlog即可,spdlog一级目录为:

-bash-4.2$ ll ../spdlog/
total 56
-rw-rw-r--. 1 centos centos   988 Dec 30 07:43 appveyor.yml
drwxrwxr-x. 2 centos centos   148 Dec 30 07:43 bench
drwxrwxr-x. 2 centos centos   116 Dec 30 07:43 cmake
-rw-rw-r--. 1 centos centos 11996 Dec 30 07:43 CMakeLists.txt
drwxrwxr-x. 2 centos centos    66 Dec 30 07:43 example
drwxrwxr-x. 3 centos centos    20 Dec 30 07:43 include
-rw-rw-r--. 1 centos centos   661 Dec 30 07:43 INSTALL
-rw-rw-r--. 1 centos centos  1142 Dec 30 07:43 LICENSE
-rw-rw-r--. 1 centos centos  4682 Dec 30 07:43 meson.build
-rw-rw-r--. 1 centos centos  1773 Dec 30 07:43 meson_options.txt
-rw-rw-r--. 1 centos centos 12669 Dec 30 07:43 README.md
drwxrwxr-x. 2 centos centos   110 Dec 30 07:43 scripts
drwxrwxr-x. 2 centos centos   125 Dec 30 07:43 src
drwxrwxr-x. 2 centos centos  4096 Dec 30 07:43 tests
-bash-4.2$ 

修改CMakeLists.txt文件,增加头文件搜索路径

INCLUDE_DIRECTORIES(
        /usr/include/
        ${PROJECT_SOURCE_DIR}/src/
        ${PROJECT_SOURCE_DIR}/include/
        ${PROJECT_SOURCE_DIR}/include/spdlog/
)

线程安全

命名空间 spdlog:: 下面的大多数方法是线程安全的。已知以下三个是线程不安全的,使用时请注意:

void spdlog::set_pattern(const std::string&);
void spdlog::set_formatter(formatter_ptr);
void spdlog::set_error_handler(log_err_handler);

日志对象的大部分方法也是线程安全的,除了:

void spdlog::logger::set_pattern(const std::string&);
void spdlog::logger::set_formatter(formatter_ptr);
void spdlog::set_error_handler(log_err_handler);

_mt的意思是multi thread(速度稍微慢一点点,考虑了多线程并发),_st的意思是single thread(速度较块)。所有以_mt结尾的SINK都是线程安全的,以_st结尾的则不是。

使用规则示例

#include "spdlog/spdlog.h"
#include <iostream>
 
// 多线程的基于控制台(stdout)的日志记录器,支持高亮。类似的stdout_color_st是单线程版本
auto console = spdlog::stdout_color_mt( "console" );
// 基于文件的简单日志
auto logger = spdlog::basic_logger_mt("basic_logger", "logs/basic.txt");
// 基于滚动文件的日志,每个文件5MB,三个文件
auto logger = spdlog::rotating_logger_mt("file_logger", "myfilename", 1024 * 1024 * 5, 3);
 
// 定制输出格式
spdlog::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");
 
// 多个日志器共享SINK
auto daily_sink = std::make_shared<spdlog::sinks::daily_file_sink_mt>("logfile", 23, 59);
// 下面几个同步日志器共享的输出到目标文件
auto net_logger = std::make_shared<spdlog::logger>("net", daily_sink);
auto hw_logger = std::make_shared<spdlog::logger>("hw", daily_sink);
auto db_logger = std::make_shared<spdlog::logger>("db", daily_sink); 
 
// 一个日志器使用多个SINK
std::vector<spdlog::sink_ptr> sinks;
sinks.push_back( std::make_shared<spdlog::sinks::stdout_sink_st>());
sinks.push_back( std::make_shared<spdlog::sinks::daily_file_sink_st>( "logfile", 23, 59 ));
auto combined_logger = std::make_shared<spdlog::logger>( "name", begin( sinks ), end( sinks ));
spdlog::register_logger( combined_logger );
 
// 异步
// 每个日志器分配8192长度的队列,队列长度必须2的幂
spdlog::set_async_mode(8192); 
// 程序退出前清理
spdlog::drop_all();
 
// 注册日志器
spdlog::register_logger(net_logger);
// 注册后,其它代码可以根据名称获得日志器
auto logger = spdlog::get(net_logger);
 
// 记录日志
// 设置最低级别
console->set_level(spdlog::level::debug);
console->debug("Hello World") ;
// 使用占位符
console->info("Hello {}" ,"World"); 
// 带格式化的占位符:d整数,x十六进制,o八进制,b二进制                
console->warn("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
// 带格式化的占位符:f浮点数
console->info("Support for floats {:03.2f}", 1.23456);
// 左对齐,保证30字符宽度
console->error("{:<30}", "left aligned");
// 指定占位符位置序号
console->info("Positional args are {1} {0}..", "too", "supported");
 
// 记录自定义类型,需要重载<<操作符
#include <spdlog/fmt/ostr.h> 
class Duck{}
std::ostream& operator<<(std::ostream& os, const Duck& duck){ 
    return os << duck.getName(); 
}
Duck duck;
console->info("custom class with operator<<: {}..", duck);

输出格式

spdlog默认的输出格式为:

[2014-31-10 23:46:59.678] [info] [my_loggername] Some message

要定制输出格式,可以调用:

spdlog::set_pattern(pattern_string);
// 示例
spdlog::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***");

或者实现自己的格式化器:

spdlog::set_formatter(std::make_shared<my_custom_formatter>());

Pattern说明

输出格式的Pattern中可以有若干 %开头的标记,含义如下表:

标记 说明
%v 实际需要被日志记录的文本,如果文本中有{占位符}会被替换
%t 线程标识符
%P 进程标识符
%n 日志记录器名称
%l 日志级别
%L 日志级别简写
%a 简写的周几,例如Thu
%A 周几,例如Thursday
%b 简写的月份,例如Aug
%B 月份,例如August
%c 日期时间,例如Thu Aug 23 15:35:46 2014
%C 两位年份,例如14
%Y 四位年份,例如2014
%D 或 %x MM/DD/YY格式日期,例如"08/23/14
%m 月份,1-12之间
%d 月份中的第几天,1-31之间
%H 24小时制的小时,0-23之间
%I 12小时制的小时,1-12之间
%M 分钟,0-59
%S 秒,0-59
%e 当前秒内的毫秒,0-999
%f 当前秒内的微秒,0-999999
%F 当前秒内的纳秒, 0-999999999
%p AM或者PM
%r 12小时时间,例如02:55:02 pm
%R 等价于%H:%M,例如23:55
%T 或 %X HH:MM:SS
%z 时区UTC偏移,例如+02:00
%+ 表示默认格式

spdlog示例

#include "spdlog/spdlog.h"
#include "spdlog/sinks/daily_file_sink.h"
#include <memory>

#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"

namespace spd = spdlog;

using namespace std;

int main(int argc, char **argv)
{
	//创建文件名类似于: daily_log_2018-01-17_10-27.txt,如果程序不退出的话,就是每天2:30 am创建新的文件
	{
		auto console= spd::daily_logger_mt("maitianPT", "./daily_log.txt", 2, 30);
		//写入文档
		console->info("test daily info 提示信息");
		console->warn("test daily warn 警告");
		console->error("test daily error 错误");
		console->critical("test daily critical 致命");
	}

	// 打印到控制台的信息,不同日志级别,颜色不同
	{
		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);		
	for (int i = 0; i < 1000; i ++)
	{
		file_logger->info("Test File Logger {}", i);
	}

	return 0;
}

在这里插入图片描述

发布了61 篇原创文章 · 获赞 63 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/jacky128256/article/details/103769794