0. 概况
0.1 源码搭建环境
源码网址:
GitHub - gabime/spdlog: Fast C++ logging library.
可以只是用头文件,也可以先编译后使用;后面的示例都是直接使用头文件的方式。
编译方法:
$ git clone https://github.com/gabime/spdlog.git
$ cd spdlog && mkdir build && cd build
$ cmake .. && make -j
0.2 一些情况
spdlog 的 6 个log等级,定义在 spdlog/include/spdlog/common.h 中,如下;
平时打开的是 INFO,小于INFO等级的log将不被记录,这起到了filter的作用。
#define SPDLOG_LEVEL_TRACE 0
#define SPDLOG_LEVEL_DEBUG 1
#define SPDLOG_LEVEL_INFO 2
#define SPDLOG_LEVEL_WARN 3
#define SPDLOG_LEVEL_ERROR 4
#define SPDLOG_LEVEL_CRITICAL 5
#define SPDLOG_LEVEL_OFF 6
通过SPDLOG_ACTIVE_LEVEL这个宏来打开默认log等级:
#if !defined(SPDLOG_ACTIVE_LEVEL)
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
#endif
可以通过调用函数
#include "spdlog/spdlog.h"
spdlog::set_level(spdlog::level::debug);
来将log等级降低到SPDLOG_LEVEL_DEBUG
因为有这样的定义:
enum level_enum
{
trace = SPDLOG_LEVEL_TRACE,
debug = SPDLOG_LEVEL_DEBUG,
info = SPDLOG_LEVEL_INFO,
warn = SPDLOG_LEVEL_WARN,
err = SPDLOG_LEVEL_ERROR,
critical = SPDLOG_LEVEL_CRITICAL,
off = SPDLOG_LEVEL_OFF,
n_levels
};
1. 第一个示例
这是最基础的使用,打印在显示器上
test.cpp
#include "spdlog/spdlog.h"int main()
{//如下方式是直接打印到屏幕上的log信息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 debugspdlog::debug("This message should be displayed.."); // change log patternspdlog::set_pattern("[%H:%M:%S %z] [%n] [%^---%L---%$] [thread %t] %v");// Compile time log levels// define SPDLOG_ACTIVE_LEVEL to desired levelSPDLOG_TRACE("Some trace message with param {}", 42);SPDLOG_DEBUG("Some debug message");
}
build:
Makefile
TARGETS = test test_stdout_stderr test_logfile example rotate_log_test daily_log_test backtrace_log stopwatch_logall: $(TARGETS)%: %.cppg++ $< -o $@ -I../spdlog/include.PHONY:clean
clean:-rm -f $(TARGETS)
2. 第二个示例
test_logfile.cpp
#include "spdlog/sinks/basic_file_sink.h"
//#include "spdlog/spdlog.h"
#include <iostream>
//using namespacevoid basic_logfile_example()
{try {// 这句返回一个指针类型 std::shared_ptr<logger>,具体定义在 spdlog/include/spdlog/sinks/basic_file_sink.h 中auto logger = spdlog::basic_logger_mt("writer ID", "logs/basic-log.txt");//这句将使用追加的方式,向文件logs/basic-log.txt中写入信息;格式是四个字段[time][writer ID][type][message]logger->info("hello spdlog world\n {}", 3.345);logger->error("hello error log {}", 78.9);logger->critical("hello critical log {}", 12,34);//spdlog::set_level(spdlog::level::debug);//需要打开#include "spdlog/spdlog.h"logger->debug("hello debug log {} ",11.11);//这句不会被记录,因为记录等级不到debug,除非事前设置记录log的等级logger->warn("hello warn log {}",77.77);//spdlog::get("logger")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name)");}catch (const spdlog::spdlog_ex &ex){std::cout << "Log init failed: " << ex.what() << std::endl;}
}int main()
{basic_logfile_example();return 0;
}
3. 第三个示例
rotate_log_test.cpp
#include "spdlog/sinks/rotating_file_sink.h"
void rotating_example()
{//如果log足够多,那么最多创建3个log文件,分别在文件名后缀加 log.1.txt log.2.txt log.3.txt,每个文件最大到5MB// Create a file rotating logger with 5 MB size max and 3 rotated filesauto max_size = 1048576 * 5;auto max_files = 3;//这句会创建一个log文件 logs/rotating_test.txtauto logger = spdlog::rotating_logger_mt("some_logger_name", "logs/rotating_test.txt", max_size, max_files);//如果一次log缓冲的数据量足够大,使用logs/rotating_test.txt的过程中,当 logs/rotating_test.txt 的文件等于5MB时,将会被首先移动(mv)成 logs/rotating_test.1.txt//如果log在logs/rotating_test.txt中再次达到5MB时,将会先把 logs/rotating_test.1.txt 移动(shell mv)成 logs/rotating_test.2.txt,再将 logs/rotating_test.txt 移动(mv)成 logs/rotating_test.1.txt//以此类推,总之直接写入的文件是logs/rotating_test.txt//下面的循环执行结束后,超过5MB,会被移动成.1.txt文件for(int i=0; i<1024*16*5;i++){logger->info("111111111");//{printf("1");}//logger->error("llo rotate errhelllllllll");}for(int i=0; i<1024*16*5;i++){logger->info("211111111");//logger->error("hello rotate errhelllllllll");}for(int i=0; i<1024*16*5;i++){//logger->info("3");logger->error("311111111");}
}int main()
{rotating_example();return 0;
}
4. 第四个示例
daily_log_test.cpp
#include "spdlog/sinks/daily_file_sink.h"
void daily_example()
{//如果是一个常驻的程序,比如服务器守护进程,那么每天都会重现创建一个log文件,即删除以前的内容,只记录当天创建之后的log信息;// Create a daily logger - a new file is created every day at 2:30 amauto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 12, 56);logger->info("hello 01");logger->info("hello 02");
}int main()
{daily_example();return 0;}
5. 第五个示例
backtrace_log.cpp
#include "spdlog/spdlog.h"int main()
{//这个 case 是一个场景应用案例,可以这么来用,仅记录本逻辑线路的最后几条log而已,记录在内存中;在需要的时候,将其dump出来。本逻辑线路的
// Debug messages can be stored in a ring buffer instead of being logged immediately.
// This is useful to display debug logs only when needed (e.g. when an error happens).
// When needed, call dump_backtrace() to dump them to your log.spdlog::enable_backtrace(32); // Store the latest 32 messages in a buffer.
// or my_logger->enable_backtrace(32)..for(int i = 0; i < 100; i++){spdlog::debug("Backtrace message {}", i); // not logged yet..}
// e.g. if some error happened:spdlog::dump_backtrace(); // log them now! show the last 32 messages
// or my_logger->dump_backtrace(32)..
//return 0;
}
6. 第六个示例
stopwatch_log.cpp
#include "spdlog/spdlog.h"
// Stopwatch support for spdlog
#include "spdlog/stopwatch.h"//码表,用于统计时间
void stopwatch_example()
{spdlog::stopwatch sw, sw2;spdlog::info("Elapsed {} {}", sw, sw2);//输出的单位是秒Sspdlog::info("Elapsed {:.3} {:.3}", sw, sw2);//重置为0,从新计时sw.reset();spdlog::info("Elapsed {:.3} {:.3}", sw, sw2);std::this_thread::sleep_for(std::chrono::milliseconds(123));//线程休眠123msspdlog::info("Elapsed {:.3} {:.3}", sw, sw2);//float s=0.0f;//
}int main()
{stopwatch_example();return 0;
}
7. 第七个示例
sinks_log.cpp
建立多个信息渠道,绑定到同一个logger上,对信息进行区别对待,根据不同的级别设置过滤本sink对信息的接受或拒绝;
#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/basic_file_sink.h"// create a logger with 2 targets, with different log levels and formats.
// The console will show only warnings or errors, while the file will log all.
void multi_sink_example()
{auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();console_sink->set_level(spdlog::level::warn);console_sink->set_pattern("[multi_sink_example] [%^%l%$] %v");auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/multisink.txt", true);file_sink->set_level(spdlog::level::trace);spdlog::logger logger("multi_sink", {console_sink, file_sink});//如果总体重新设计,将会导致前面的单独设置失效//logger.set_level(spdlog::level::debug);//logger.warn("this should appear in both console and file");logger.info("this message should not appear in the console, only in the file");
}int main()
{multi_sink_example();return 0;
}
sinks_log的效果:
另外为了及时全部存盘,还有如下函数 flush_every()
//用来控制强制存盘的时间周期,用来防止断电丢失太多日志信息。
// periodically flush all *registered* loggers every 3 seconds:
// warning: only use if all your loggers are thread-safe ("_mt" loggers)
spdlog::flush_every(std::chrono::seconds(3));