日志系统——日志器管理模块

日志器管理类

日志器管理类管理着所有全局日志器,负责向用户提供获取指定名称日志器,全局中应该有且仅有一份,所以需要设置为单例模式。

?类属性
*默认日志器 (落地方向是显示屏,免去用户自己构造落地方向为显示屏的日志器)
*日志器数组
*锁 (日志器通过哈希表组织,锁用来保护stl容器线程安全)
?类方法
*添加日志器
*获取日志器
*判断日志器存在性

class LoggerManage
{
private:
    std::shared_ptr<logger::Logger> _default_logger;
    std::unordered_map<std::string, std::shared_ptr<logger::Logger>> _logger_map; //每一个全局日志器的名称独一无二
    std::mutex _mtx;

public:
    static LoggerManage *getInstance(); //获取日志器管理单例对象
    void addLogger(const std::shared_ptr<logger::Logger> &item);	//添加新的全局日志器
    std::shared_ptr<logger::Logger> getLogger(const std::string &name = ""); //获取指定名称的日志器,如果name为空表示获取默认日志器

private:
    LoggerManage();
    bool exist(const std::string &name); //判断用户获取的日志器是否存在
};
LoggerManage *LoggerManage::getInstance()
{
    static LoggerManage obj;
    return &obj;
}

LoggerManage::LoggerManage()
{
    std::unique_ptr<logger::LoggerBuilder> builder(new logger::LocalLoggerBuilder);
    //! 不能使用Global,此时单例对象还未构造完毕
    builder->buildName("default");
    _default_logger = builder->build();
    _logger_map.insert({"default", _default_logger});
}

bool LoggerManage::exist(const std::string &name)
{
    if (_logger_map.find(name) != _logger_map.end())
        return true;
    return false;
}

void LoggerManage::addLogger(const std::shared_ptr<logger::Logger> &item)
{
    // todo name重复情况处理 unique_ptr
    std::lock_guard<std::mutex> lock(_mtx);
    _logger_map.insert({item->getName(), item});
}

std::shared_ptr<logger::Logger> LoggerManage::getLogger(const std::string &name)
{
    if (name.empty())
        return _logger_map["default"];
    if (exist(name))
        return _logger_map[name];
    return std::shared_ptr<logger::Logger>(nullptr); //不存在返回一个空指针,外层进行判空操作
}

完善日志器具体建造者

日志器根据作用域来分分为局部日志器和全局日志器,二者的build函数只有一个区别,那就是全局日志器建造者会把日志器对象加入日志器管理对象的哈希表中

 class GlobalLoggerBuilder : public LoggerBuilder
    {
    public:
        virtual std::shared_ptr<Logger> build() override;
    };
std::shared_ptr<logger::Logger> logger::GlobalLoggerBuilder::build()
{
    assert(!_name.empty());
    if (_formater.get() == nullptr)
        _formater = std::make_shared<Formater>();
    if (_lands.empty())
        _lands.emplace_back(land::LandFactory::create<land::StdoutLogLand>());
    if (_mode == Mode::SYN)
    {
        auto ptr = std::make_shared<logger::SynLogger>(_name, _formater, _lands, _limit_level); //*
        LoggerManage::getInstance()->addLogger(ptr);//*
        return ptr;
    }
    else
    {
        auto ptr = std::make_shared<logger::AsynLogger>(_name, _formater, _lands, _limit_level);//*
        LoggerManage::getInstance()->addLogger(ptr);//*
        return ptr;
    }
}
/*局部日志器建造者只需要在全局日志器的基础上去掉*标记处即可*/

通过代理模式进一步简化用户操作

在此之前,用户每一次获取日志器对象之前都需要先调用getInstance获取单例对象,并且在之后调用日志器提供的debug~fatal一系列方法时都需要手动传入__FILE__,__LINE__较为繁琐,因此可以考虑通过基于代理模式的宏函数替换来简化操作

std::shared_ptr<logger::Logger> getLogger(const std::string &name = "")
{
    return LoggerManage::getInstance()->getLogger(name);
    /*用户直接通过全局函数getLogger就可直接获取日志器,函数内部自动获取单例对象*/
}
#define debug(fmt, ...) debug(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define info(fmt, ...) info(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define warn(fmt, ...) warn(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define error(fmt, ...) error(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define fatal(fmt, ...) fatal(__FILE__, __LINE__, fmt, ##__VA_ARGS__)

/*对于默认日志器的打印操作更加简单,甚至不需要手动获取*/
#define DEBUG(fmt, ...) chxlog::getLogger()->debug(fmt, ##__VA_ARGS__)
#define INFO(fmt, ...) chxlog::getLogger()->info(fmt, ##__VA_ARGS__)
#define WARN(fmt, ...) chxlog::getLogger()->warn(fmt, ##__VA_ARGS__)
#define ERROR(fmt, ...) chxlog::getLogger()->error(fmt, ##__VA_ARGS__)
#define FATAL(fmt, ...) chxlog::getLogger()->fatal(fmt, ##__VA_ARGS__)


^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  • 12
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Shall#

你的鼓励将是我前进的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值