用于调试的c++日志库-spdlog

(9 mins to read)

使用

1
git clone --depth 1 https://github.com/gabime/spdlog.git

header-only 所以直接include头文件即可,当然也可以install成静态库

1
2
3
4
target_include_directories(xxx
PRIVATE
spdlog/include
)

日志级别:info、warn、error、critical

mt后缀表示多线程(multi threaded),st后缀表示单线程

spdlog takes the “include what you need” approach - your code should includethe features that actually needed.

输出使用fmt库,类似python

编译器log过滤

1
2
3
4
5
6
7
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG

spdlog::set_level(spdlog::level::debug); // or spdlog::set_level(spdlog::level::trace);

SPDLOG_LOGGER_TRACE(file_logger , "Some trace message that will not be evaluated.{} ,{}", 1, 3.23);
SPDLOG_LOGGER_DEBUG(file_logger , "Some Debug message that will be evaluated.. {} ,{}", 1, 3.23);
SPDLOG_DEBUG("Some debug message to default logger that will be evaluated");

set level

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
spdlog::set_level(spdlog::level::info); // Set global log level to info
spdlog::debug("This message should not be displayed!");
spdlog::set_level(spdlog::level::trace); // Set specific logger's log level
spdlog::debug("This message should be displayed..");
```cpp

backtrace

```cpp
// Backtrace support
// Loggers can store in a ring buffer all messages (including debug/trace) for later inspection.
// When needed, call dump_backtrace() to see what happened:
spdlog::enable_backtrace(10); // create ring buffer with capacity of 10 messages
for (int i = 0; i < 100; i++) {
spdlog::debug("Backtrace message {}", i); // not logged..
}
// e.g. if some error happened:
spdlog::dump_backtrace(); // log them now!

shutdown

1
2
3
// Release all spdlog resources, and drop all loggers in the registry.
// This is optional (only mandatory if using windows + async log).
spdlog::shutdown();

logger

Each logger contains a vector of one or morestd::shared_ptr<spdlog::sink>.

On each log call (if the log level is right) the logger will call thesink(log_msg) function on each of them.

spdlog会默认创建一个全局的logger(stdout、color、mt),直接使用spdlog::info(..)调用的就是该logger

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
spdlog::set_default_logger(some_other_logger);
spdlog::info("Use the new default logger");

auto console = spdlog::stdout_color_mt("some_unique_name"); // create logger

auto file_logger = spdlog::rotating_logger_mt("file_logger", "logs/mylogfile", 1048576 * 5, 3); // rotate 3个文件循环log

auto sink = std::make_shared<spdlog::sinks::stdout_sink_mt>();
auto my_logger= std::make_shared<spdlog::logger>("mylogger", sink); // manually,不会register

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)); // one log and multiple sink
//register it if you need to access it globally
spdlog::register_logger(combined_logger);

sink

log和sink都分别由st和mt

logger的功能由sink决定

1
2
3
4
5
6
7
8
9
10
11
logger:
spdlog::rotating_logger_mt
spdlog::daily_logger_mt
spdlog::basic_logger_mt
spdlog::stdout_logger_mt
spdlog::stderr_logger_st
spdlog::stdout_color_mt
spdlog::stderr_color_st
-----------------------
sink:
example:spdlog::sinks::rotating_file_sink_mt

register

spdlog maintains a global (per process) registry of the created loggers.

The purpose is for loggers to be accessed easily from anywhere in theproject without passing them around.(避免参数传递)

1
2
3
4
5
spdlog::get("logger_name"); // 内部有lock,最好使用一个变量保存
spdlog::register_logger(some_logger);
spdlog::drop("logger_name");
//or remove them all
spdlog::drop_all()

format

1
2
3
spdlog::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***"); // global to all
some_logger->set_pattern(">>>>>>>>> %H:%M:%S %z %v <<<<<<<<<");
some_logger->sinks()[0]->set_pattern(">>>>>>>>> %H:%M:%S %z %v <<<<<<<<<");