四川简阳建设局招标公告网站,校园文化设计公司 案例,长安网站建设流程,手工做环保衣的网站文章目录 专栏导读日志器建造者类完善单例日志器管理类设计思想单例日志器管理类设计全局建造者类设计日志器类、建造者类整理日志器管理类测试 专栏导读 #x1f338;作者简介#xff1a;花想云 #xff0c;在读本科生一枚#xff0c;C/C领域新星创作者#xff0c;新星计… 文章目录 专栏导读日志器建造者类完善单例日志器管理类设计思想单例日志器管理类设计全局建造者类设计日志器类、建造者类整理日志器管理类测试 专栏导读 作者简介花想云 在读本科生一枚C/C领域新星创作者新星计划导师阿里云专家博主CSDN内容合伙人…致力于 C/C、Linux 学习。 专栏简介本文收录于 C项目——基于多设计模式下的同步与异步日志系统 相关专栏推荐C语言初阶系列、C语言进阶系列 、C系列、数据结构与算法、Linux 日志器建造者类完善
实现了异步日志器设计之后将异步日志器添加到日志器建造者类当中。
// 1.抽象一个日志器建造者类完成日志器所需零部件的构建 日志器的构建
// 1.设置日志器类型
// 2.将不同类型的日志器的创建放到同一个日志器建造者类中完成
enum class LoggerType
{LOGGER_SYNC,LOGGER_ASYNC
};
class LoggerBuilder
{
public:LoggerBuilder() : _logger_type(LoggerType::LOGGER_SYNC),_limit_level(LogLevel::value::DEBUG),_looper_type(AsyncType::ASYNC_SAFE){}void buildLoggerType(LoggerType type) { _logger_type type; }void buildEnableUnSafeAsync() { _looper_type AsyncType::ASYNC_UNSAFE; }void buildLoggerName(const std::string name) { _logger_name name; }void buildLoggerLevel(LogLevel::value level) { _limit_level level; }void buildFormatter(const std::string pattern){_formatter std::make_sharedFormatter(pattern);}template typename SinkType, typename... Argsvoid buildSink(Args ...args) // 由用户自己决定落地方式{LogSink::ptr psink SinkFactory::createSinkType(std::forwardArgs(args)...);_sinks.push_back(psink);}virtual Logger::ptr build() 0;
protected:AsyncType _looper_type;LoggerType _logger_type;std::string _logger_name;std::atomicLogLevel::value _limit_level;Formatter::ptr _formatter;std::vectorLogSink::ptr _sinks;
};
/*2.派生出具体的建造者类---局部日志器的建造者 全局日志器的建造者*/
class LocalLoggerBuilder : public LoggerBuilder
{
public:Logger::ptr build() override{assert(_logger_name.empty() false);if (_formatter.get() nullptr){_formatter std::make_sharedFormatter();}if (_sinks.empty()){buildSinkStdOutSink();}if (_logger_type LoggerType::LOGGER_ASYNC){return std::make_sharedAsyncLogger(_logger_name, _limit_level, _formatter, _sinks, _looper_type);}return std::make_sharedSyncLogger(_logger_name, _limit_level, _formatter, _sinks);}
};单例日志器管理类设计思想
通过局部日志器建造者创建的日志器受到作用域的限制。但是日志的输出我们希望能够在任意位置。
因此为了突破日志器作用域的限制我们创建一个日志器管理类且该类是一个单例类这样我们就可以在任意位置通过单例管理器单例获取到指定的日志器进行输出了。
基于单例日志器管理类的设计思想我们对于日志器建造者类进行继承继承出一个全局日志器建造者类实现一个日志器在创建完毕后直接将其添加到单例的日志器管理器当中以便于能够在任意位置通过日志器名称能够获取到指定的日志器进行输出。
日志器管理器的作用
对所有创建的日志器进行管理可以在程序的任意位置进获取相同的单例对象获取其中的日志器进行日志输出
单例日志器管理类设计
管理的成员
默认日志器所管理的日志器数组使用哈希表日志器名称为key日志器对象为value互斥锁
提供的操作
添加日志器管理判断是否管理了指定名称的日志器获取指定名称的日志器获取默认日志器
class LoggerManager
{
public:static LoggerManager getInstance(){// c11之后静态局部变量编译器在编译的层面实现了线程安全// 当静态局部变量在没有构造完成之前其他线程进入就会阻塞static LoggerManager eton;return eton;}void addLogger(Logger::ptr logger){if(hasLogger(logger-name())) return;std::unique_lockstd::mutex lock(_mutex);_loggers.insert(std::make_pair(logger-name(), logger));}bool hasLogger(const std::string name){std::unique_lockstd::mutex lock(_mutex);auto it _loggers.find(name);if(it _loggers.end()){return false;}return true;}Logger::ptr getLogger(const std::string name){std::unique_lockstd::mutex lock(_mutex);auto it _loggers.find(name);if(it _loggers.end()){return Logger::ptr();}return it-second;}Logger::ptr rootLogger(){return _root_logger;}
private:// 构造函数私有化LoggerManager(){std::unique_ptrLOG::LoggerBuilder builder(new LOG::LocalLoggerBuilder());builder-buildLoggerName(root);_root_logger builder-build();_loggers.insert(std::make_pair(root, _root_logger));}
private:std::mutex _mutex;Logger::ptr _root_logger; // 默认日志器std::unordered_mapstd::string, Logger::ptr _loggers // 日志器数组;
};全局建造者类设计
为了降低用户的使用复杂度我们提供一个全局日志器建造者类。全局建造者类的设计思想非常简单即在局部的基础上增加了一个功能
将日志器添加到单例对象中。
class GlobalLoggerBuilder : public LoggerBuilder
{
public:Logger::ptr build() override{assert(_logger_name.empty() false);if (_formatter.get() nullptr){_formatter std::make_sharedFormatter();}if (_sinks.empty()){buildSinkStdOutSink();}Logger::ptr logger;if (_logger_type LoggerType::LOGGER_ASYNC){logger std::make_sharedAsyncLogger(_logger_name, _limit_level, _formatter, _sinks, _looper_type);}else{logger std::make_sharedSyncLogger(_logger_name, _limit_level, _formatter, _sinks);}LoggerManager::getInstance().addLogger(logger);return logger;}
};日志器类、建造者类整理
#ifndef __M_LOGGER_H__
#define __M_LOGGER_H__
#include util.hpp
#include level.hpp
#include format.hpp
#include sink.hpp
#include looper.hpp
#include cstdarg
#include atomic
#include thread
#include mutex
#include unordered_mapnamespace LOG
{class Logger{public:using ptr std::shared_ptrLogger;Logger(const std::string logger_name,LogLevel::value level,Formatter::ptr formatter,std::vectorLogSink::ptr sinks) : _logger_name(logger_name),_limit_level(level),_formatter(formatter),_sinks(sinks.begin(), sinks.end()){}const std::string name(){ return _logger_name; }void debug(const std::string file, size_t line, const std::string fmt, ...){// 通过传入的参数构造出一个日志消息对象 进行日志格式化最终落地// 判断当前的日志是否达到了输出等级if (LogLevel::value::DEBUG _limit_level){return;}// 对fmt格式化字符串和不定参数进行字符串组织 得到的日志消息字符串va_list ap;va_start(ap, fmt);char *res;int ret vasprintf(res, fmt.c_str(), ap);if (ret 1){std::cout vasprintf failed\n;return;}va_end(ap);serialize(LogLevel::value::DEBUG, file, line, res);free(res);}void info(const std::string file, size_t line, const std::string fmt, ...){// 通过传入的参数构造出一个日志消息对象 进行日志格式化最终落地if (LogLevel::value::INFO _limit_level){return;}// 对fmt格式化字符串和不定参数进行字符串组织 得到的日志消息字符串va_list ap;va_start(ap, fmt);char *res;int ret vasprintf(res, fmt.c_str(), ap);if (ret 1){std::cout vasprintf failed\n;return;}va_end(ap);serialize(LogLevel::value::INFO, file, line, res);free(res);}void warn(const std::string file, size_t line, const std::string fmt, ...){// 通过传入的参数构造出一个日志消息对象 进行日志格式化最终落地if (LogLevel::value::WARN _limit_level){return;}// 对fmt格式化字符串和不定参数进行字符串组织 得到的日志消息字符串va_list ap;va_start(ap, fmt);char *res;int ret vasprintf(res, fmt.c_str(), ap);if (ret 1){std::cout vasprintf failed\n;return;}va_end(ap);serialize(LogLevel::value::WARN, file, line, res);free(res);}void error(const std::string file, size_t line, const std::string fmt, ...){// 通过传入的参数构造出一个日志消息对象 进行日志格式化最终落地if (LogLevel::value::ERROR _limit_level){return;}// 对fmt格式化字符串和不定参数进行字符串组织 得到的日志消息字符串va_list ap;va_start(ap, fmt);char *res;int ret vasprintf(res, fmt.c_str(), ap);if (ret 1){std::cout vasprintf failed\n;return;}va_end(ap);serialize(LogLevel::value::ERROR, file, line, res);free(res);}void fatal(const std::string file, size_t line, const std::string fmt, ...){// 通过传入的参数构造出一个日志消息对象 进行日志格式化最终落地if (LogLevel::value::FATAL _limit_level){return;}// 对fmt格式化字符串和不定参数进行字符串组织 得到的日志消息字符串va_list ap;va_start(ap, fmt);char *res;int ret vasprintf(res, fmt.c_str(), ap);if (ret 1){std::cout vasprintf failed\n;return;}va_end(ap);serialize(LogLevel::value::FATAL, file, line, res);free(res);}protected:void serialize(LogLevel::value level, const std::string file, size_t line, char *str){// 构造LogMsg对象LogMsg msg(level, line, file, _logger_name, str);// 通过格式化工具对LogMsg进行格式化 得到格式化后的日志字符串std::stringstream ss;_formatter-format(ss, msg);// 对日志进行落地log(ss.str().c_str(), ss.str().size());}virtual void log(const char *data, size_t len) 0;protected:std::mutex _mutex;std::string _logger_name; // 日志器名称std::atomicLogLevel::value _limit_level; // 限制输出等级Formatter::ptr _formatter;std::vectorLogSink::ptr _sinks;};class SyncLogger : public Logger{public:SyncLogger(const std::string logger_name,LogLevel::value level,LOG::Formatter::ptr formatter,std::vectorLogSink::ptr sinks) : Logger(logger_name, level, formatter, sinks){}protected:void log(const char *data, size_t len){std::unique_lockstd::mutex lock(_mutex);if (_sinks.empty())return;for (auto sink : _sinks){sink-log(data, len);}}};class AsyncLogger : public Logger{public:AsyncLogger(const std::string logger_name,LogLevel::value level,LOG::Formatter::ptr formatter,std::vectorLogSink::ptr sinks,AsyncType looper_type): Logger(logger_name, level, formatter, sinks),_looper(std::make_sharedAsyncLooper(std::bind(AsyncLogger::realLog, this, std::placeholders::_1), looper_type)){}// 将数据写入缓冲区 void log(const char *data, size_t len){_looper-push(data, len);}// 设计一个实际落地函数void realLog(Buffer buf){if (_sinks.empty())return;for (auto sink : _sinks){sink-log(buf.begin(), buf.readAbleSize());}}private:AsyncLooper::ptr _looper; // 异步工作器};// 1.抽象一个日志器建造者类完成日志器所需零部件的构建 日志器的构建// 1.设置日志器类型// 2.将不同类型的日志器的创建放到同一个日志器建造者类中完成enum class LoggerType{LOGGER_SYNC,LOGGER_ASYNC};class LoggerBuilder{public:LoggerBuilder() : _logger_type(LoggerType::LOGGER_SYNC),_limit_level(LogLevel::value::DEBUG),_looper_type(AsyncType::ASYNC_SAFE){}void buildLoggerType(LoggerType type) { _logger_type type; }void buildEnableUnSafeAsync() { _looper_type AsyncType::ASYNC_UNSAFE; }void buildLoggerName(const std::string name) { _logger_name name; }void buildLoggerLevel(LogLevel::value level) { _limit_level level; }void buildFormatter(const std::string pattern){_formatter std::make_sharedFormatter(pattern);}template typename SinkType, typename... Argsvoid buildSink(Args ...args) // 由用户自己决定落地方式{LogSink::ptr psink SinkFactory::createSinkType(std::forwardArgs(args)...);_sinks.push_back(psink);}virtual Logger::ptr build() 0;protected:AsyncType _looper_type;LoggerType _logger_type;std::string _logger_name;std::atomicLogLevel::value _limit_level;Formatter::ptr _formatter;std::vectorLogSink::ptr _sinks;};/*2.派生出具体的建造者类---局部日志器的建造者 全局日志器的建造者*/class LocalLoggerBuilder : public LoggerBuilder{public:Logger::ptr build() override{assert(_logger_name.empty() false);if (_formatter.get() nullptr){_formatter std::make_sharedFormatter();}if (_sinks.empty()){buildSinkStdOutSink();}if (_logger_type LoggerType::LOGGER_ASYNC){return std::make_sharedAsyncLogger(_logger_name, _limit_level, _formatter, _sinks, _looper_type);}return std::make_sharedSyncLogger(_logger_name, _limit_level, _formatter, _sinks);}};class LoggerManager{public:static LoggerManager getInstance(){// c11之后静态局部变量编译器在编译的层面实现了线程安全// 当静态局部变量在没有构造完成之前其他线程进入就会阻塞static LoggerManager eton;return eton;}void addLogger(Logger::ptr logger){if(hasLogger(logger-name())) return;std::unique_lockstd::mutex lock(_mutex);_loggers.insert(std::make_pair(logger-name(), logger));}bool hasLogger(const std::string name){std::unique_lockstd::mutex lock(_mutex);auto it _loggers.find(name);if(it _loggers.end()){return false;}return true;}Logger::ptr getLogger(const std::string name){std::unique_lockstd::mutex lock(_mutex);auto it _loggers.find(name);if(it _loggers.end()){return Logger::ptr();}return it-second;}Logger::ptr rootLogger(){return _root_logger;}private:// 构造函数私有化LoggerManager(){std::unique_ptrLOG::LoggerBuilder builder(new LOG::LocalLoggerBuilder());builder-buildLoggerName(root);_root_logger builder-build();_loggers.insert(std::make_pair(root, _root_logger));}private:std::mutex _mutex;Logger::ptr _root_logger; // 默认日志器std::unordered_mapstd::string, Logger::ptr _loggers // 日志器数组;};class GlobalLoggerBuilder : public LoggerBuilder{public:Logger::ptr build() override{assert(_logger_name.empty() false);if (_formatter.get() nullptr){_formatter std::make_sharedFormatter();}if (_sinks.empty()){buildSinkStdOutSink();}Logger::ptr logger;if (_logger_type LoggerType::LOGGER_ASYNC){logger std::make_sharedAsyncLogger(_logger_name, _limit_level, _formatter, _sinks, _looper_type);}else{logger std::make_sharedSyncLogger(_logger_name, _limit_level, _formatter, _sinks);}LoggerManager::getInstance().addLogger(logger);return logger;}};
}#endif日志器管理类测试
#include logger.hppvoid log_test()
{LOG::Logger::ptr logger LOG::LoggerManager::getInstance().getLogger(async_logger);logger-debug(__FILE__, __LINE__, %s, 测试日志);logger-info(__FILE__, __LINE__, %s, 测试日志);logger-warn(__FILE__, __LINE__, %s, 测试日志);logger-error(__FILE__, __LINE__, %s, 测试日志);logger-fatal(__FILE__, __LINE__, %s, 测试日志);size_t count 0;while(count 300000){ logger-fatal(__FILE__, __LINE__, 测试日志-%d, count);}
}
int main()
{ std::unique_ptrLOG::LoggerBuilder builder(new LOG::GlobalLoggerBuilder());builder-buildLoggerName(async_logger);builder-buildLoggerLevel(LOG::LogLevel::value::WARN);builder-buildFormatter([%c]%m%n);builder-buildLoggerType(LOG::LoggerType::LOGGER_ASYNC);builder-buildEnableUnSafeAsync();builder-buildSinkLOG::FileSink(./logfile/async.log);builder-buildSinkLOG::StdOutSink();builder-build();log_test();return 0;
}