当前位置: 首页 > news >正文

东莞市建设企业网站服务机构陕西建设银行缴费网站

东莞市建设企业网站服务机构,陕西建设银行缴费网站,wordpress 1g1核1m,固定ip做网站路由设置前面的文章中我们讲述了日志系统项目的前置知识点#xff0c;再本文中我们将开始日志项目的细节实现。 日志系统框架设计 本项目实现的是一个多日志器日志系统#xff0c;主要实现的功能是让程序员能够轻松的将程序运行日志信息落地到指定的位置#xff0c;且支持同步与异…前面的文章中我们讲述了日志系统项目的前置知识点再本文中我们将开始日志项目的细节实现。 日志系统框架设计 本项目实现的是一个多日志器日志系统主要实现的功能是让程序员能够轻松的将程序运行日志信息落地到指定的位置且支持同步与异步两种方式的日志落地方式。 项目的框架设计将项目分为以下几个模块来实现。 模块划分 日志等级模块对输出日志的等级进行划分以便于控制日志的输出并提供等级枚举转字符串功能。 OFF关闭DEBUG调试调试时的关键信息输出。INFO提示普通的提示型日志信息。WARN警告不影响运行但是需要注意一下的日志。ERROR错误程序运行出现错误的日志。FATAL致命一般是代码异常导致程序无法继续推进运行的日志。 日志消息模块中间存储日志输出所需的各项要素信息 时间描述本条日志的输出时间。线程ID描述本条日志是哪个线程输出的。日志等级描述本条日志的等级。日志数据本条日志的有效载荷数据。日志文件名描述本条日志在哪个源码文件中输出的。日志行号描述本条日志在源码文件的哪一行输出的。 日志消息格式化模块设置日志输出格式并提供对日志消息进行格式化功能。 系统的默认日志输出格式%d{%H:%M:%S}%T[9%t]%T[%p]%T[%c]%T%f:%1%T%m%no -13:26:32 [2343223321] [FATAL] [root] main.c:76 套接字创建失败\n%d{%H:%M:%S}表示日期时间花括号中的内容表示日期时间的格式。%T表示制表符缩进。%t表示线程ID。%p表示日志级别。%c表示日志器名称不同的开发组可以创建自己的日志器进行日志输出小组之间互不影响。%f表示日志输出时的源代码文件名。%l表示日志输出时的源代码行号。%m表示给与的日志有效载荷数据。%n表示换行。设计思想:设计不同的子类不同的子类从日志消息中取出不同的数据进行处理。 日志消息落地模块∶决定了日志的落地方向可以是标准输出也可以是日志文件也可以滚动文件输出… 标准输出表示将日志进行标准输出的打印。日志文件输出表示将日志写入指定的文件末尾。滚动文件输出当前以文件大小进行控制当一个日志文件大小达到指定大小则切换下一个文件进行输出后期也可以扩展远程日志输出创建客户端将日志消息发送给远程的日志分析服务器。设计思想设计不同的子类不同的子类控制不同的日志落地方向。 日志器模块 此模块是对以上几个模块的整合模块用户通过日志器进行日志的输出有效降低用户的使用难度。包含有:日志消息落地模块对象日志消息格式化模块对象日志输出等级 日志器管理模块 为了降低项目开发的日志耦合不同的项目组可以有自己的日志器来控制输出格式以及落地方向因此本项目是一个多日志器的日志系统。管理模块就是对创建的所有日志器进行统一管理。并提供一个默认日志器提供标准输出的日志输出。 异步线程模块: 实现对日志的异步输出功能用户只需要将输出日志任务放入任务池异步线程负责日志的落地输出功能以此提供更加高效的非阻塞日志输出。 模块关系图 代码设计 实用类设计 完成一些零碎的功能接口以便于后面会用到。 获取系统时间信息判断文件是否存在获取文件所在路径创建目录 /*实用工具类的实现1. 获取系统时间2. 判断文件是否存在3. 获取文件所在目录4. 创建目录 */ namespace zyqlog {namespace util{class Date {public:static size_t now() // 获取当前的系统时间{return (size_t)time(nullptr);}};class File{public:static bool exists(const std::string pathname) // 判断当前的文件是否存在{// return (access(pathname.c_str(), F_OK) 0); // Linux下的接口struct stat st;if (stat(pathname.c_str(), st) 0){return false;}return true;}static std::string path(const std::string pathname) // 获取当前的文件路径{// ./abc/a.txtsize_t pos pathname.find_last_of(/\\); // 从文件路径最后的一个/或者\\开始获取文件路径if (pos std::string::npos) return .;return pathname.substr(0, pos 1);}static void createDirectory(const std::string pathname){// ./abc/bcd/a.txtsize_t pos 0, idx 0;while (idx pathname.size()){pos pathname.find_first_of(/\\, idx); // 从文件路径开始处的/或者\\开始获取文件路径if (pos std::string::npos) // 获取到的结果如果已到文件末尾则说明传入的整个路径名都是需要创建的目录直接进行创建{mkdir(pathname.c_str(), 0777);}std::string parent_dir pathname.substr(0, pos 1); // 将获取到的每级目录进行截取if (parent_dir . || parent_dir ..) // 如果截取的目录是当前目录或者是上一级目录则继续进行截取。{idx pos 1;continue;}if (exists(parent_dir) true) // 如果目录已经存在则继续进行截取{idx pos 1;continue;}mkdir(parent_dir.c_str(), 0777); // 创建截取得到的未创建目录idx pos 1;}}};} }/*test*/ std::cout zyqlog::util::Date().now() std::endl; std::string pathname ./abc/bcd/a.txt; zyqlog::util::File().createDirectory(zyqlog::util::File::path(pathname));日志等级类设计 日志等级共分为7个等级分别为 OFF 关闭所有日志输出DRBUG 进行debug时候打印日志的等级INFO 打印一些用户提示信息WARN 打印警告信息ERROR 打印错误信息FATAL 打印致命信息-导致程序崩溃的信息 /*1. 定义枚举类枚举出日志等级2. 提供转换接口将枚举转换为对应的字符串 */ namespace zyqlog {class LogLevel{private:public:enum class value // 枚举类实现不同的日志等级{UNKNOW 0,DEBUG,INFO,WARNING,ERROR,FATAL,OFF};static const char *toString(LogLevel::value level) // 将获取到的日志等级转换为字符串{switch (level){case LogLevel::value::DEBUG:return DEBUG;case LogLevel::value::INFO:return INFO;case LogLevel::value::WARNING:return WARNING;case LogLevel::value::ERROR:return ERROR;case LogLevel::value::FATAL:return FATAL;case LogLevel::value::OFF:return OFF;}return UNKNOW;}}; }日志消息类设计 /*定义日志消息类进行日志中间信息的存储1. 日志的输出时间--用于过滤日志输出时间2. 日志等级--用于进行日志过滤分析3. 源文件名称4. 源代码行号--用于定位出现错误的代码的位置5. 线程ID--用于过滤出错的线程6. 日志主体消息7. 日志器名称--支持多日志器同时使用 */ namespace zyqlog {struct LogMsg{time_t _ctime; // 日志产生的时间戳LogLevel::value _level; // 日志等级std::thread::id _tid; // 线程IDsize_t _line; // 行号std::string _file; // 源码文件名std::string _logger; // 日志器名称std::string _payload; // 有效消息数据LogMsg() {}LogMsg(LogLevel::value level, size_t line, const std::string file, const std::string logger, const std::string msg) : _ctime(util::Date::now()), _level(level), _line(line), _tid(std::this_thread::get_id()), _file(file), _logger(logger), _payload(msg){}}; }日志格式化输出类 日志格式化Formatter类主要负责格式化日志消息。其主要包含以下内容 pattern成员保存日志输出的格式字符串 %d 日期%T 缩进%t 线程id%p 日志级别%c 日志器名称%f 文件名%l 行号%m 日志消息%n 换行 std::vector FormatItem::ptr items成员用于按序保存格式化字符串对应的子格式化对象 FormatItem类主要负责日志消息子项的获取及格式化。其包含以下子类MsgFormatItem表示要从LogMsg中取出有效日志数据LevelFormatItem表示要从LogMsg中取出日志等级ThreadFormatItem表示要从LogMsg中取出线程IDTimeFormatItem表示要从LogMsg中取出时间戳并按照指定格式进行格式化LineFormatItem表示要从LogMsg中取出源码所在行号TabFormatItem表示⼀个制表符缩进NLineFormatItem表示⼀个换行OtherFormatItem表示非格式化的原始字符串 格式化的过程其实就是按次序从Msg中取出需要的数据进行字符串的连接的过程。 // 设计思想 // 1. 抽象一个格式化子项基类 // 2. 基于基类, 派生出格式化子项子类// 在父类中定义父类指针数组,指向不同格式化子类对象 namespace zyqlog {// 抽象格式化子项基类class FormatItem{public:using ptr std::shared_ptrFormatItem;virtual void format(std::ostream out, const LogMsg msg) 0;};// 派生类格式化子项子类--消息等级时间文件名行号线程ID日志器名制表符换行吗其他class MsgFormatItem : public FormatItem{public:void format(std::ostream out, const LogMsg msg) override{out msg._payload;}};class LevelFormatItem : public FormatItem{public:void format(std::ostream out, const LogMsg msg) override{out LogLevel::toString(msg._level);}};class TimeFormatItem : public FormatItem{public:TimeFormatItem(const std::string fmt %H:%M:%S) :_time_fmt(fmt) {}void format(std::ostream out, const LogMsg msg) override{struct tm t;localtime_r(msg._ctime, t);char tmp[32] {0};strftime(tmp, 31, _time_fmt.c_str(), t); // strftime()函数根据格式字符串将给定的日期和时间从给定的日历时间转换为以空结尾的多字节字符串。out tmp;}private:std::string _time_fmt; // %H:%M:%S};class FileFormatItem : public FormatItem{public:void format(std::ostream out, const LogMsg msg) override{out msg._file;}};class LineFormatItem : public FormatItem{public:void format(std::ostream out, const LogMsg msg) override{out msg._line;}};class ThreadFormatItem : public FormatItem{public:void format(std::ostream out, const LogMsg msg) override{out msg._tid;}};class LoggerFormatItem : public FormatItem{public:void format(std::ostream out, const LogMsg msg) override{out msg._logger;}};class TabFormatItem : public FormatItem{public:void format(std::ostream out, const LogMsg msg) override{out \t;}};class NLineFormatItem : public FormatItem{public:void format(std::ostream out, const LogMsg msg) override{out \n;}};class OtherFormatItem : public FormatItem{public:OtherFormatItem(const std::string str) :_str(str) {}void format(std::ostream out, const LogMsg msg) override{out _str;}private:std::string _str;};/*%d 表示日期 包含子格式{%H:%M:%S}%t 表示线程ID %c 表示日志器名称%f 表示源码文件名%l 表示源码行号%p 表示日志级别%T 表示制表符缩进%m 日志消息%n 表示换行*/class ForMatter{public:using ptr std::shared_ptrForMatter;ForMatter(const std::string pattern [%d{%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n) : _pattern(pattern) {assert(parsePattern()); // 对格式化规则字符串进行解析}// 对msg进行格式化void format(std::ostream out, LogMsg msg){for(auto item : _items){item-format(out, msg);}}std::string format(LogMsg msg){std::stringstream ss;format(ss, msg);return ss.str();}private:// 对格式化规则字符串进行解析bool parsePattern(){// 1. 对格式化规则字符串进行解析// abcd[ % d {%H:%M:%S} ][ %t][%c][%f:%l][%p]%T%m%nstd::vectorstd::pairstd::string, std::string fmt_order;size_t pos 0;std::string key, val;while (pos _pattern.size()){// 1. 处理原始字符串--判断是否是%不是就是原始字符if (_pattern[pos] ! %){val.push_back(_pattern[pos]);continue;}// 能进行到此说明pos位置是%字符%%处理称为一个%字符if (pos 1 _pattern.size() _pattern[pos 1] %){val.push_back(%);pos 2;continue;}// 这时候原始字符串处理完毕if (!val.empty()){fmt_order.push_back(std::make_pair(, val));val.clear();}//代表%后面是一个格式化字符格式化字符的处理pos 1; // pos指向格式化字符的位置if (pos _pattern.size()) {std::cerr %之后没有对应的字符!\n;return false;}key _pattern[pos]; // 确定key格式化字符的位置// 此时pos指向格式化字符后的位置pos 1;if (pos _pattern.size() _pattern[pos] {) {pos 1; // pos指向子规则的起始位置while (pos _pattern.size() _pattern[pos] ! }){val.push_back(_pattern[pos]);}// 走到末尾跳出循环则代表没有遇到}代表格式是错误的if (pos _pattern.size()) {std::cerr 子规则{}匹配出错!\n;return false;}pos 1; // pos指向}位置向后走一步到了下一步的位置}fmt_order.push_back(std::make_pair(key, val));key.clear();val.clear();}/*这个处理的过程以 abcd[%d{%H:%M:%S}][ %t][%c][%f:%l][%p]%T%m%n 为例子进行解析key nullptrval abcd[key dval %H:%M:%Skey nullptrval ][...得到数组内容之后根据数组内容创建格式化子项对象添加到items成员数组中。*/// 2. 根据解析得到的数据初始化格式化子项数组成员for (auto it : fmt_order){_items.push_back(createItem(it.first, it.second));}return true;}// 根据不同格式化字符创建不同的格式化子项对象FormatItem::ptr createItem(const std::string key, const std::string val){if (key d) return std::make_sharedTimeFormatItem(val);if (key t) return std::make_sharedThreadFormatItem();if (key c) return std::make_sharedLoggerFormatItem();if (key f) return std::make_sharedFileFormatItem();if (key l) return std::make_sharedLineFormatItem();if (key p) return std::make_sharedLevelFormatItem();if (key T) return std::make_sharedTabFormatItem();if (key m) return std::make_sharedMsgFormatItem();if (key n) return std::make_sharedNLineFormatItem();if (key.empty()) return std::make_sharedOtherFormatItem(val);std::cerr 没有对应的格式化字符: % key std::endl;abort();return FormatItem::ptr();}private:std::string _pattern; // 格式化规则字符串std::vectorFormatItem::ptr _items;}; }
http://www.w-s-a.com/news/219584/

相关文章:

  • 巢湖网站建设电话长沙大型互联网公司
  • wordpress站群主机海南人
  • 云南网站建设维护商业网站建设教程
  • 云南省滇中引水工程建设管理局网站jsp个人网站设计
  • 网站建设 域名业务 邮箱互联网装饰网站
  • 建设厅技工在哪个网站上查询有了网站模板 还要怎样做
  • 城市联盟网站怎么做百度云网站建设视频教程
  • 织梦cms 官方网站网页视频如何下载到电脑
  • 查询建设公司业绩网站国外外链平台
  • 搭建直播网站需要怎么做做石材网站步骤
  • 移动网站如何做权重wordpress 统计字数 插件
  • 编写网站的软件百度指数教程
  • 网站改版建议策划书做设计什么兼职网站
  • 北京做兼职网站文创产品设计流程
  • 南阳做玉器网站wordpress 图片被缩小
  • 自己做网站卖衣服cms做网站容易不
  • 安徽安搜做的网站怎么样手机网站商城建设答辩问题
  • 分析不同网站的优缺点房产网站定制
  • 深圳工业设计大展2021论坛与网站做优化哪个更好
  • 什么网站做招聘比较好网络营销渠道管理
  • 网站建设选择什么模式淘宝网站可以做轮播吗
  • 山西免费网站制作乌市高新区建设局网站
  • 公司网站建设费用会计处理手机app免费下载
  • 网站的做网站的公司网站有些什么内容
  • 网站新类型wordpress 随机文章
  • 电商网站建设会计分录朝阳市网站公司
  • 正邦网站建设 优帮云百姓网征婚
  • 企业网站有哪些举几个例子端午节网站建设目的
  • 南京免费发布信息网站网站建设与管理职责
  • 无锡市建设培训中心网站企业vi设计是啥