攻略

今亮点!第四部分:Spdlog日志库的核心组件分析-logger

  • 来源:博客园
  • 时间:2023-03-28 17:30:48

Spdlog是一个快速且可扩展的C++日志库,它支持多线程和异步日志记录。在本文中,我们将分析Spdlog日志库的核心代码,探究其实现原理和代码结构。

Spdlog的基本架构

上一篇文章介绍了spdlog的五个主要组件,其中最重要是Logger、Sink和Formatter其中,Logger负责日志的记录和管理,Sink负责将日志输出到不同的目标(比如控制台、文件、网络等),Formatter负责将日志格式化为字符串。我们会在下面详细的介绍下它们。

Logger

Logger是Spdlog日志库的核心组件,它负责记录和管理日志。Logger的定义如下:


(资料图片)

class logger {public:    explicit logger(std::string logger_name, sinks_init_list sinks);    template    void log(level::level_enum lvl, const T &msg);    template    void log(source_loc loc, level::level_enum lvl, format_string_t fmt, Args &&... args);        template    void log(level::level_enum lvl, format_string_t fmt, Args &&... args);        // ...    template    void trace(format_string_t fmt, Args &&... args);        template    void debug(format_string_t fmt, Args &&... args);    template    void info(format_string_t fmt, Args &&... args);    // ....private:    std::string name_;    std::vector sinks_;    // ...};

Logger主要包含一个名称和一组Sink,它还提供了log()方法用于记录日志。当调用log()方法时,Logger会将日志消息传递给每个Sink,并由Sink将日志输出到目标。Logger还提供了其他一些方法,比如设置日志级别、添加和删除Sink等。

Logger 是个日志包装器,包含了日志名称和一组Sink,它提供了输出不同级别日志的方法,通过不同Sink的组合可以输出到一个或多个不同输出路径(文件,控制台,网络等)。

日志名全局唯一

每个 logger都有一个名称,并且是全局唯一的,通过上一篇提到的 register组件注册到全局的 map里,代码如下, registryloggers_字段通过名字记录了所有的 logger实例。

class registry{public:    // .....     // 注册日志  void register_logger(std::shared_ptr new_logger); private:  // ....std::unordered_map> 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 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类中提供的不同级别日志输出接口的代码示例:

templatevoid trace(format_string_t fmt, Args &&... args);templatevoid debug(format_string_t fmt, Args &&... args);templatevoid info(format_string_t fmt, Args &&... args);templatevoid warn(format_string_t fmt, Args &&... args);templatevoid error(format_string_t fmt, Args &&... args);templatevoid critical(format_string_t fmt, Args &&... args);

使用这些接口,可以根据不同的日志级别输出不同的日志信息,比如 logger.info("This is an info message.");将输出一条信息级别为 info的日志。

日志输出级别控制

logger提供了 set_level接口来设置日志级别,这个级别可以是枚举类型 level中的任何一个,比如 spdlog::set_level(spdlog::level::trace);将设置日志级别为 trace,这样所有级别的日志都会被记录下来。如果想要只记录 info级别及以上的日志,则可以使用 spdlog::set_level(spdlog::level::info);

如果想要在运行时动态地设置日志级别,可以使用 set_level()方法,例如 logger->set_level(spdlog::level::trace);将设置当前 logger的日志级别为 trace

注意:如果想要关闭日志,则可以将日志级别设置为 off,例如 spdlog::set_level(spdlog::level::off);

enum class level{    trace,    debug,    info,    warn,    err,    critical,    off};
日志刷新控制

logger提供了一些控制日志刷新的方法,最重要的方法是flush()。当调用flush()方法时,Logger会将所有挂起的日志消息刷新到Sink中。Logger还提供了set_pattern()方法,用于设置日志格式化模式。这个方法可以用于修改日志的输出格式,例如添加时间戳、线程ID等信息。

void flush();
日志格式设置

logger提供了设置日志格式的方法 set_pattern通过此方法可以设置包含的 skin的日志格式,具体的格式信息可以参考上一篇。

// 日志格式设置void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local);

通过格式字符串 pattern,会生成 formatter实例,调用 skin的set_formatter接口设置日志格式。

SPDLOG_INLINE void logger::set_pattern(std::string pattern, pattern_time_type time_type){    auto new_formatter = details::make_unique(std::move(pattern), time_type);    set_formatter(std::move(new_formatter));}// set formatting for the sinks in this logger.// each sink will get a separate instance of the formatter object.SPDLOG_INLINE void logger::set_formatter(std::unique_ptr f){    for (auto it = sinks_.begin(); it != sinks_.end(); ++it)    {        if (std::next(it) == sinks_.end())        {            // last element - we can be move it.            (*it)->set_formatter(std::move(f));            break; // to prevent clang-tidy warning        }        else        {            (*it)->set_formatter(f->clone());        }    }}

关键词:

推荐内容

Copyright @  2015-2022 太平洋旅行网版权所有  

备案号:豫ICP备2022016495号-17

  

联系邮箱:93 96 74 66 9@qq.com