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

高安市帮助做公司网站seo工资一般多少

高安市帮助做公司网站,seo工资一般多少,茂名企业网站开发,房产网络获客平台有哪些前面的文章中我们讲述了日志系统项目的前置知识点,再本文中我们将开始日志项目的细节实现。 日志系统框架设计 本项目实现的是一个多日志器日志系统,主要实现的功能是让程序员能够轻松的将程序运行日志信息落地到指定的位置,且支持同步与异…

前面的文章中我们讲述了日志系统项目的前置知识点,再本文中我们将开始日志项目的细节实现。

日志系统框架设计

本项目实现的是一个多日志器日志系统,主要实现的功能是让程序员能够轻松的将程序运行日志信息落地到指定的位置,且支持同步与异步两种方式的日志落地方式。
项目的框架设计将项目分为以下几个模块来实现。

模块划分

  • 日志等级模块:对输出日志的等级进行划分,以便于控制日志的输出,并提供等级枚举转字符串功能。

    • 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中取出线程ID
  • TimeFormatItem:表示要从LogMsg中取出时间戳并按照指定格式进行格式化
  • LineFormatItem:表示要从LogMsg中取出源码所在行号
  • TabFormatItem:表示⼀个制表符缩进
  • NLineFormatItem:表示⼀个换行
  • OtherFormatItem:表示非格式化的原始字符串

格式化的过程其实就是按次序从Msg中取出需要的数据进行字符串的连接的过程。

// 设计思想:
// 1. 抽象一个格式化子项基类
// 2. 基于基类, 派生出格式化子项子类// 在父类中定义父类指针数组,指向不同格式化子类对象
namespace zyqlog
{// 抽象格式化子项基类class FormatItem{public:using ptr = std::shared_ptr<FormatItem>;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_ptr<ForMatter>;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::vector<std::pair<std::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 = nullptr,val = abcd[key = d,val = %H:%M:%Skey = nullptr,val = ][...得到数组内容之后,根据数组内容,创建格式化子项对象,添加到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_shared<TimeFormatItem>(val);if (key == "t") return std::make_shared<ThreadFormatItem>();if (key == "c") return std::make_shared<LoggerFormatItem>();if (key == "f") return std::make_shared<FileFormatItem>();if (key == "l") return std::make_shared<LineFormatItem>();if (key == "p") return std::make_shared<LevelFormatItem>();if (key == "T") return std::make_shared<TabFormatItem>();if (key == "m") return std::make_shared<MsgFormatItem>();if (key == "n") return std::make_shared<NLineFormatItem>();if (key.empty()) return std::make_shared<OtherFormatItem>(val);std::cerr << "没有对应的格式化字符: %" << key << std::endl;abort();return FormatItem::ptr();}private:std::string _pattern; // 格式化规则字符串std::vector<FormatItem::ptr> _items;};
}
http://www.tj-hxxt.cn/news/119375.html

相关文章:

  • 免费下ppt的网站有哪些国内永久免费域名注册
  • wordpress如何写个插件进一步优化营商环境
  • 西安做的好的网站公司商务网站如何推广
  • 深圳市移动端网站建设个人网络销售平台
  • b2c购物关键词搜索优化公司
  • java如何进行网站开发百度经验实用生活指南
  • 如何做制作头像的网站球队世界排名榜
  • wordpress主题乱码河南seo外包
  • 邯郸做网站网络营销讲师
  • 做网站有没有效果网络营销名词解释答案
  • 福建省城乡住房建设厅网站南京百度快照优化排名
  • 建个什么网站赚钱公司网站如何推广
  • b2c 网站有哪些网页设计公司
  • ps网站主页按钮怎么做外贸网站大全
  • 自己做网站排名好吗网络营销图片素材
  • 广告体验程序网站开发宁波seo资源
  • 简单网站建设公司成都网站建设方案托管
  • 做网站能赚钱么百度品牌专区怎么收费
  • 一般公司网站是什么设计师做关键字广告
  • 环球资源网的网站特色做一个网站需要多少钱大概
  • 拉新十大推广app平台aso优化师
  • 网站如何静态化企业关键词推广
  • 视频网站开发工程师株洲seo排名
  • 专做婴儿的网站seo积分优化
  • 广东注册公司在哪个网站申请seo外链发布平台有哪些
  • 网站设置手机才能播放网站建设加推广优化
  • iis默认网站在哪里物联网开发
  • 做网站需要画原型图么厦门网站制作全程服务
  • 办理一个网站做英语教学济南网站优化
  • 月夜直播在线观看视频免费播放深圳百度首页优化