上一篇文章介绍了spdlog
的五个主要组件,其中最重要是Logger
、Sink
和Formatter
其中,Logger
负责日志的记录和管理,Sink
负责将日志输出到不同的目标(比如控制台、文件、网络等),Formatter
负责将日志格式化为字符串。我们会在下面详细的介绍下它们。
Logger Logger
是Spdlog
日志库的核心组件,它负责记录和管理日志。Logger
的定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 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
是个日志包装器,包含了日志名称和一组Sink
,它提供了输出不同级别日志的方法,通过不同Sink
的组合可以输出到一个或多个不同输出路径(文件,控制台,网络等)。
日志名全局唯一 每个 logger
都有一个名称,并且是全局唯一的,通过上一篇提到的 register
组件注册到全局的 map里,代码如下, registry
的 loggers_
字段通过名字记录了所有的 logger
实例。
1 2 3 4 5 6 7 8 9 10 11 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
抛出异常。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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
类中提供的不同级别日志输出接口的代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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) ;template <typename ... Args>void warn (format_string_t <Args...> fmt, Args &&... args) ;template <typename ... Args>void error (format_string_t <Args...> fmt, Args &&... args) ;template <typename ... Args>void critical (format_string_t <Args...> 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);
。
1 2 3 4 5 6 7 8 9 10 enum class level { trace, debug, info, warn, err, critical, off };
日志刷新控制 logger
提供了一些控制日志刷新的方法,最重要的方法是flush()
。当调用flush()
方法时,Logger
会将所有挂起的日志消息刷新到Sink
中。Logger
还提供了set_pattern()
方法,用于设置日志格式化模式。这个方法可以用于修改日志的输出格式,例如添加时间戳、线程ID等信息。
日志格式设置 logger
提供了设置日志格式的方法 set_pattern
通过此方法可以设置包含的 sink
的日志格式,具体的格式信息可以参考上一篇。
1 2 void set_pattern (std::string pattern, pattern_time_type time_type = pattern_time_type::local) ;
通过格式字符串 pattern
,会生成 formatter
实例,调用 sink
的set_formatter
接口设置日志格式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 SPDLOG_INLINE void logger::set_pattern (std::string pattern, pattern_time_type time_type) { auto new_formatter = details::make_unique <pattern_formatter>(std::move (pattern), time_type); set_formatter (std::move (new_formatter)); } SPDLOG_INLINE void logger::set_formatter (std::unique_ptr<formatter> f) { for (auto it = sinks_.begin (); it != sinks_.end (); ++it) { if (std::next (it) == sinks_.end ()) { (*it)->set_formatter (std::move (f)); break ; } else { (*it)->set_formatter (f->clone ()); } } }
参考链接:https://zhuanlan.zhihu.com/p/617706483