【C++】C++11 第三方开源LOG日志库-spdlog (1)
1. 安装,直接在github搜索spdlog
spdlog是基于C++ 11的日志组件,它非常轻量,使用时你仅仅需要引入头文件就可以了。
Header only version
Copy the include folder to your build tree and use a C++11 compiler.
Static lib version (recommended - much faster compile times)
$ git clone https://github.com/gabime/spdlog.git $ cd spdlog && mkdir build && cd build $ cmake .. && make -j
see example CMakeLists.txt on how to use.
Platforms
- Linux, FreeBSD, OpenBSD, Solaris, AIX
- Windows (msvc 2013+, cygwin)
- macOS (clang 3.5+)
- Android
Package managers:
- Debian:
sudo apt install libspdlog-dev
- Homebrew:
brew install spdlog
- MacPorts:
sudo port install spdlog
- FreeBSD:
pkg install spdlog
- Fedora:
dnf install spdlog
- Gentoo:
emerge dev-libs/spdlog
- Arch Linux:
pacman -S spdlog
- vcpkg:
vcpkg install spdlog
- conan:
spdlog/[>=1.4.1]
- conda:
conda install -c conda-forge spdlog
- build2:
depends: spdlog ^1.8.2
2. 多线程注意事项
名字空间 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结尾的SINK都是线程安全的,以_st结尾的则不是。
3. 官方范例代码
#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);
4. 个人最喜欢的功能:可控制格式和行号输出
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>());
在github的手册中给出了官方支持的格式说明:
标记 | 说明 |
---|---|
%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 |
%+ | 表示默认格式 |