spdlog源码分析:logger

首先看logger的成员变量,对logger有个大概的了解

const std::string _name;    /*有一个名字,名字唯一,不能重复*/
std::vector<sink_ptr> _sinks;/*有一组输出目标*/
formatter_ptr _formatter;   /*格式化输出信息*/
spdlog::level_t _level;     /*日志等级*/
spdlog::level_t _flush_level;/*冲刷等级,大于此等级的日志会调用flush*/

所以,我们向logger输出日志的时候,它会用相同的格式化输出,同时输出到多个目标。

logger的创建

template<class It>
std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
{
    /*锁保护,有单、多线程锁,单线程锁什么都不做*/
    std::lock_guard<Mutex> lock(_mutex);
    /*如果名字重复会抛出异常*/
    throw_if_exists(logger_name);
    /*根据是否异步模式创建logger*/
    std::shared_ptr<logger> new_logger;
    if (_async_mode)
        new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms, _worker_teardown_cb);
    else
        new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end);
    /*设置格式化输出信息为全局格式化输出信息*/
    if (_formatter)
        new_logger->set_formatter(_formatter);
    /*设置日志等级*/
    new_logger->set_level(_level);
    //Add to registry
    _loggers[logger_name] = new_logger;
    return new_logger;
}

logger创建后就可以向它写入日志了

template <typename... Args>
inline void spdlog::logger::log(level::level_enum lvl, const char* fmt, const Args&... args)
{
    /*日志等级限制*/
    if (!should_log(lvl)) return;
    /*格式化基本日志*/
    details::log_msg log_msg(&_name, lvl);
    try
    {
        log_msg.raw.write(fmt, args...);
    }
    catch (fmt::FormatError &ex)
    {
        throw spdlog::spdlog_ex(std::string("format error in \"") + fmt + "\": " + ex.what());
    }
    /*遍历输出目标,向每个sink输出一次日志*/
    _sink_it(log_msg);
}

inline void spdlog::logger::_sink_it(details::log_msg& msg)
{
    _formatter->format(msg);
    for (auto &sink : _sinks)
        sink->log(msg);

    const auto flush_level = _flush_level.load(std::memory_order_relaxed);
    if (msg.level >= flush_level)
        flush();
}

同时,spdlog提供了一些快捷函数用于创建常用的logger,带后缀mt的是多线程版本,带后缀st的是单线程版本。

//
// Create and register multi/single basic file logger
//
std::shared_ptr<logger> basic_logger_mt(const std::string& logger_name, const filename_t& filename,bool force_flush = false);
std::shared_ptr<logger> basic_logger_st(const std::string& logger_name, const filename_t& filename, bool force_flush = false);

//
// Create and register multi/single threaded rotating file logger
//
std::shared_ptr<logger> rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files, bool force_flush = false);
std::shared_ptr<logger> rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files, bool force_flush = false);

//
// Create file logger which creates new file on the given time (default in midnight):
//
std::shared_ptr<logger> daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0, bool force_flush = false);
std::shared_ptr<logger> daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0, bool force_flush = false);

//
// Create and register stdout/stderr loggers
//
std::shared_ptr<logger> stdout_logger_mt(const std::string& logger_name, bool color = false);
std::shared_ptr<logger> stdout_logger_st(const std::string& logger_name, bool color = false);
std::shared_ptr<logger> stderr_logger_mt(const std::string& logger_name, bool color = false);
std::shared_ptr<logger> stderr_logger_st(const std::string& logger_name, bool color = false);

你可能感兴趣的:(C++,spdlog)