Spdlog的基本架构
上一篇文章介绍了spdlog的五个主要组件,其中最重要是Logger、Sink和Formatter其中,Logger负责日志的记录和管理,Sink负责将日志输出到不同的目标(比如控制台、文件、网络等),Formatter负责将日志格式化为字符串。我们会在下面详细的介绍下它们。
Logger
class logger {
public:
explicit logger(std::string logger_name, sinks_init_list sinks;
template<typename T>
void log(level::level_enum lvl, const T &msg;
template<typename... Args>
void log(source_loc loc, level::level_enum lvl, format_string_t<Args...> fmt, Args &&... args;
template<typename... Args>
void log(level::level_enum lvl, format_string_t<Args...> fmt, Args &&... args;
// ...
template<typename... Args>
void trace(format_string_t<Args...> fmt, Args &&... args;
template<typename... Args>
void debug(format_string_t<Args...> fmt, Args &&... args;
template<typename... Args>
void info(format_string_t<Args...> fmt, Args &&... args;
// ....
private:
std::string name_;
std::vector<sink_ptr> sinks_;
// ...
};
Logger主要包含一个名称和一组Sink,它还提供了log(方法用于记录日志。当调用log(方法时,Logger会将日志消息传递给每个Sink,并由Sink将日志输出到目标。Logger还提供了其他一些方法,比如设置日志级别、添加和删除Sink等。
日志名全局唯一
每个 logger
都有一个名称,并且是全局唯一的,通过上一篇提到的 register
组件注册到全局的 map里,代码如下,registry
的 loggers_
字段通过名字记录了所有的 logger
实例。
class registry
{
public:
// .....
// 注册日志
void register_logger(std::shared_ptr<logger> new_logger;
private:
// ....
std::unordered_map<std::string, std::shared_ptr<logger>> loggers_;
}
registry
提供register_logger
接口注册日志。这里值得注意点是:注册时候如果发现已经存在则会抛异常,throw_if_exists_
会检查是否已经存在同名日志实例,存在则通过throw_spdlog_ex
抛出异常。SPDLOG_INLINE void registry::throw_if_exists_(const std::string &logger_name { if (loggers_.find(logger_name != loggers_.end( { throw_spdlog_ex("logger with name '" + logger_name + "' already exists"; } } SPDLOG_INLINE void registry::register_logger_(std::shared_ptr<logger> new_logger { auto logger_name = new_logger->name(; throw_if_exists_(logger_name; loggers_[logger_name] = std::move(new_logger; }
日志输出控制
- 提供不同级别日志的输出接口
在 logger
类中,Spdlog 提供了不同级别日志的输出接口,包括 trace(
、debug(
、info(
、warn(
、error(
和 critical(
等。下面是 logger
类中提供的不同级别日志输出接口的代码示例: