日志器管理类
日志器管理类管理着所有全局日志器,负责向用户提供获取指定名称日志器,全局中应该有且仅有一份,所以需要设置为单例模式。
?类属性
*默认日志器 (落地方向是显示屏,免去用户自己构造落地方向为显示屏的日志器)
*日志器数组
*锁 (日志器通过哈希表组织,锁用来保护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__)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^