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

日志器管理类

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

?类属性

*默认日志器 (落地方向是显示屏,免去用户自己构造落地方向为显示屏的日志器)

*日志器数组

*锁 (日志器通过哈希表组织,锁用来保护stl容器线程安全)

?类方法

*添加日志器

*获取日志器

*判断日志器存在性

cpp 复制代码
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); //判断用户获取的日志器是否存在
};
cpp 复制代码
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函数只有一个区别,那就是全局日志器建造者会把日志器对象加入日志器管理对象的哈希表中

cpp 复制代码
 class GlobalLoggerBuilder : public LoggerBuilder
    {
    public:
        virtual std::shared_ptr<Logger> build() override;
    };
cpp 复制代码
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__较为繁琐,因此可以考虑通过基于代理模式的宏函数替换来简化操作

cpp 复制代码
std::shared_ptr<logger::Logger> getLogger(const std::string &name = "")
{
    return LoggerManage::getInstance()->getLogger(name);
    /*用户直接通过全局函数getLogger就可直接获取日志器,函数内部自动获取单例对象*/
}
cpp 复制代码
#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__)


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

相关推荐
一丝晨光23 分钟前
gcc 1.c和g++ 1.c编译阶段有什么区别?如何知道g++编译默认会定义_GNU_SOURCE?
c语言·开发语言·c++·gnu·clang·gcc·g++
南城花随雪。34 分钟前
Spring框架之装饰者模式 (Decorator Pattern)
java·开发语言·装饰器模式
究极无敌暴龙战神X40 分钟前
前端学习之ES6+
开发语言·javascript·ecmascript
虞书欣的61 小时前
Python小游戏24——小恐龙躲避游戏
开发语言·python·游戏·小程序·pygame
Komorebi.py1 小时前
【Linux】-学习笔记03
linux·笔记·学习
FHYAAAX1 小时前
【机器学习】任务十:从函数分析到机器学习应用与BP神经网络
开发语言·python
汉克老师1 小时前
GESP4级考试语法知识(贪心算法(四))
开发语言·c++·算法·贪心算法·图论·1024程序员节
程序员劝退师_1 小时前
Kafka学习笔记
笔记·学习·kafka
爱吃生蚝的于勒2 小时前
C语言最简单的扫雷实现(解析加原码)
c语言·开发语言·学习·计算机网络·算法·游戏程序·关卡设计
Ai 编码助手2 小时前
Go语言 实现将中文转化为拼音
开发语言·后端·golang