spdlog源码分析:日志输出目标sink

来源:互联网 发布:淘宝的卖家中心在哪儿 编辑:程序博客网 时间:2024/05/29 06:54

spdlog提供了多种输出目标:环形日志,每日日志,控制台日志,syslog日志,并且可以自己进行扩展。在选择输出目标的同时,我们可以选择使用单线程或多线程版本。日志输出目标的基类是sink,有两个虚函数需要实现。

class sink{public:    virtual ~sink() {}    /*日志输出*/    virtual void log(const details::log_msg& msg) = 0;    /*冲刷日志,清出缓存中的日志*/    virtual void flush() = 0;};

在sink的基础上,又提供单、多线程选择的base_sink,通过模板Mutex选择单、多线程版本

template<class Mutex>class base_sink:public sink{public:    base_sink():_mutex() {}    virtual ~base_sink() = default;    base_sink(const base_sink&) = delete;    base_sink& operator=(const base_sink&) = delete;    void log(const details::log_msg& msg) override    {        /*锁保护,如果是单线程,这个锁什么也不做*/        std::lock_guard<Mutex> lock(_mutex);        _sink_it(msg);    }protected:    virtual void _sink_it(const details::log_msg& msg) = 0;    Mutex _mutex;};

这样一来,实现一个日志输出目标只需实现两个虚函数_sink_it和flush,比如控制台日志

template <class Mutex>class stdout_sink : public base_sink<Mutex>{    using MyType = stdout_sink<Mutex>;public:    stdout_sink() {}    static std::shared_ptr<MyType> instance()    {        static std::shared_ptr<MyType> instance = std::make_shared<MyType>();        return instance;    }    void _sink_it(const details::log_msg& msg) override    {        fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stdout);        flush();    }    void flush() override    {        fflush(stdout);    }};

单线程日志使用的锁是null_mutex,多线程使用的锁是mutex

typedef stdout_sink<details::null_mutex> stdout_sink_st;typedef stdout_sink<std::mutex> stdout_sink_mt;

null_mutex什么都不做

struct null_mutex{    void lock() {}    void unlock() {}    bool try_lock()    {        return true;    }};
0 0
原创粉丝点击