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

中国网新重庆长沙seo外包优化

中国网新重庆,长沙seo外包优化,app开发企业网站建设,上海网站建设一般多少钱概述 该模块主要实现了一个日志系统的输出模块,通过多态、工厂模式等设计模式,构建灵活的日志输出架构。 功能:格式化完成的标准日志消息,输出到指定为止拓展:支持同时将日志落地到不同的位置,也就是输出日…

概述

该模块主要实现了一个日志系统的输出模块,通过多态、工厂模式等设计模式,构建灵活的日志输出架构。

  • 功能:格式化完成的标准日志消息,输出到指定为止
  • 拓展:支持同时将日志落地到不同的位置,也就是输出日志到不同位置
  • 输出位置
    • 标准输出:输出到屏幕上,主要用于测试日志是否正常运行
    • 指定文件:将日志信息输出到指定文件中,便于事后进行日志分析
    • 滚动文件:文件按照大小或者时间输出到指定文件中,方便按日期或者大小删除日志消息
  • 实现思想
    • 首先抽象出落地模块类
      • 根据不同落地方向,从基类派生出来即可
    • 其次工厂模式,创建与表示分离

架构设计

整体架构分析

  • 主框架定义了一个日志输出系统,包含多种日志输出方式,例如标准输出、文件输出、滚动文件输出
  • 模块代码通过基类 LogSink定义了一个统一的接口,并且通过派生类 StdoutSink 、 FileSink 、RollSink实现具体的日志输出方式
  • SinkFactory工厂类则是通过模版方法提供创建不同类型日志输出对象的功能
    • 保证单一职责原则,一个类派生类只负责一种日志输出方式

具体实现

LogSink基类

  • 定义所有日志输出的基类,参数分别接收日志的内容以及长度
class LogSink {
public:using ptr = std::shared_ptr<LogSink>;LogSink() {}virtual ~LogSink() {}virtual void log(const char *data, size_t len) = 0;
};

StdoutSink

  • 作用:实现将日志输出到显示器(标准输出)的功能
  • 实现逻辑: 使用std::cout::write标准库函数,输出一段指定长度的字符数据,一般用于二进制数据或者特定格式的字符串
class StdoutSink : public LogSink {
public:using ptr = std::shared_ptr<StdoutSink>;StdoutSink() = default;void log(const char *data, size_t len) {std::cout.write(data, len);}
};

FileSink

  • 功能:实现将日志写入到指定文件中
  • 实现逻辑 
    • 构造函数接收一个文件名filename,用于指定日志输出的指定文件
    • util::file::create_directory函数则是确保日志文件目录是否存在,如果不存在则对该目录进行创建
    • _ofs.oen:表示以二进制追加模式打开文件,如果文件不存在则会创建它
    • log函数则是通过write逻辑实现数据写入
    • _ofs.good():检查写操作是否成功,如果失败则输出错误信息
class FileSink : public LogSink {
public:using ptr = std::shared_ptr<FileSink>;FileSink(const std::string &filename): _filename(filename) {util::file::create_directory(util::file::path(filename));_ofs.open(_filename, std::ios::binary | std::ios::app);assert(_ofs.is_open());}const std::string &file() { return _filename; }void log(const char *data, size_t len) {_ofs.write((const char*)data, len);if (_ofs.good() == false) {std::cout << "日志输出文件失败!\n";}}
private:std::string _filename;std::ofstream _ofs;
};

RollSink

  • 功能:滚动日志功能的实现,也就是当日志文件达到一定大小的时候,自动生成新的日志文件继续写入
  • 实现逻辑
    • 构造函数:初始化日志文件基本信息,_basename文件名(基础文件名,后面可以加上拓展文件名),_max_fsize最大文件大小
    • initLogFile:检查当前日志文件的大小,如果文件已经达到设定的最大文件大小或是文件没有打开,则关闭当前文件并创建新的日志文件
    • createFilename函数:根据当前的时间,生成新的日志文件名,文件名中包含的有日期和时间,同时于要保证每个文件名的唯一性
    • Log函数;首先初始化日志文件(调用initLogFile函数)确保日志已经准备好,然后将日志数据写入到文件中,最后更新当前文件大小_cur_fsize
class RollSink : public LogSink {
public:using ptr = std::shared_ptr<RollSink>;RollSink(const std::string &basename, size_t max_fsize):_basename(basename), _max_fsize(max_fsize), _cur_fsize(0) {util::file::create_directory(util::file::path(basename));}void log(const char *data, size_t len) {initLogFile();_ofs.write(data, len);if (_ofs.good() == false) {std::cout << "日志输出文件失败!\n";}_cur_fsize += len;}
private:void initLogFile() {if (_ofs.is_open() == false || _cur_fsize >= _max_fsize) {_ofs.close();std::string name = createFilename();_ofs.open(name, std::ios::binary | std::ios::app);assert(_ofs.is_open());_cur_fsize = 0;return;}return;}std::string createFilename() {time_t t = time(NULL);struct tm lt;localtime_r(&t, &lt);std::stringstream ss;ss << _basename;ss << lt.tm_year + 1900;ss << lt.tm_mon + 1;ss << lt.tm_mday;ss << lt.tm_hour;ss << lt.tm_min;ss << lt.tm_sec;ss << ".log";return ss.str();}
private:std::string _basename;std::ofstream _ofs;size_t _max_fsize;size_t _cur_fsize;
};

SinkFactory

  • 作用:工厂类,主要用于创建各种LogSInk对象
  • 实现逻辑 
    • 通过模板函数 createSinkFactory 可以创建任意类型的 LogSink 派生类对象
    • 使用 std::make_shared<SinkType> 创建对象,std::forward<Args>(args)... 用于完美转发构造函数的参数,使得对象的创建既高效又灵活
class SinkFactory {
public:template<typename SinkType, typename ...Args>static LogSink::ptr create(Args &&...args) {return std::make_shared<SinkType>(std::forward<Args>(args)...);}
};

单元测试

功能测试1:简单测试其功能

 

#include "sink.hpp"
#include <iostream>
#include <string>
#include <cstring>  int main() {// 创建并测试 StdoutSink(标准输出日志){bitlog::LogSink::ptr stdoutSink = bitlog::SinkFactory::create<bitlog::StdoutSink>();const char* message = "这是一个用于测试 StdoutSink 的消息。\n";stdoutSink->log(message, strlen(message));}// 创建并测试 FileSink(文件输出日志){std::string filename = "test_log.txt";bitlog::LogSink::ptr fileSink = bitlog::SinkFactory::create<bitlog::FileSink>(filename);const char* message = "这是一个用于测试 FileSink 的消息。\n";fileSink->log(message, strlen(message));// 检查文件是否生成并输出文件内容std::ifstream ifs(filename);if (ifs.is_open()) {std::cout << "FileSink 测试通过。日志文件内容:\n";std::string line;while (std::getline(ifs, line)) {std::cout << line << std::endl;}ifs.close();} else {std::cout << "FileSink 测试失败。无法打开日志文件。\n";}}// 创建并测试 RollSink(滚动文件日志){std::string basename = "test_roll_log";size_t max_fsize = 50; // 小文件大小以便快速测试滚动bitlog::LogSink::ptr rollSink = bitlog::SinkFactory::create<bitlog::RollSink>(basename, max_fsize);const char* message1 = "这是用于测试 RollSink 的第一条日志消息。\n";const char* message2 = "这是用于测试 RollSink 的第二条日志消息。这条消息较长,用于触发滚动功能。\n";rollSink->log(message1, strlen(message1));rollSink->log(message2, strlen(message2));// 检查是否生成多个日志文件for (int i = 0; i < 2; ++i) {std::string rollFilename = basename + std::to_string(1900 + localtime(nullptr)->tm_year)+ std::to_string(1 + localtime(nullptr)->tm_mon)+ std::to_string(localtime(nullptr)->tm_mday)+ std::to_string(localtime(nullptr)->tm_hour)+ std::to_string(localtime(nullptr)->tm_min)+ std::to_string(localtime(nullptr)->tm_sec + i)+ ".log";std::ifstream ifs(rollFilename);if (ifs.is_open()) {std::cout << "RollSink 测试通过。日志文件 " << rollFilename << " 内容:\n";std::string line;while (std::getline(ifs, line)) {std::cout << line << std::endl;}ifs.close();} else {std::cout << "RollSink 测试失败。无法打开日志文件 " << rollFilename << "。\n";}}}return 0;
}

 复杂测试,并发场景下多种日志格式以及滚动日志

#include "sink.hpp"
#include <iostream>
#include <string>
#include <cstring>
#include <thread>
#include <vector>
#include <chrono>
#include <atomic>// 模拟多线程日志写入的函数
void thread_log(bitlog::LogSink::ptr sink, const std::string& prefix, int num_messages, std::atomic<int>& counter) {for (int i = 0; i < num_messages; ++i) {std::string message = prefix + " 线程 " + std::to_string(counter++) + ": 日志消息 " + std::to_string(i + 1) + "\n";sink->log(message.c_str(), message.size());std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 模拟写入间隔}
}int main() {std::atomic<int> counter(1); // 用于标记每条日志的编号// 测试并发写入到 StdoutSink{bitlog::LogSink::ptr stdoutSink = bitlog::SinkFactory::create<bitlog::StdoutSink>();std::vector<std::thread> threads;// 启动多个线程进行并发日志写入for (int i = 0; i < 5; ++i) {threads.emplace_back(thread_log, stdoutSink, "StdoutSink", 10, std::ref(counter));}for (auto& t : threads) {t.join(); // 等待所有线程完成}std::cout << "StdoutSink 并发测试完成。\n";}// 测试多线程写入到 FileSink{std::string filename = "complex_test_log.txt";bitlog::LogSink::ptr fileSink = bitlog::SinkFactory::create<bitlog::FileSink>(filename);std::vector<std::thread> threads;// 启动多个线程进行并发日志写入for (int i = 0; i < 5; ++i) {threads.emplace_back(thread_log, fileSink, "FileSink", 10, std::ref(counter));}for (auto& t : threads) {t.join(); // 等待所有线程完成}std::cout << "FileSink 并发测试完成。日志文件:" << filename << "\n";}// 测试复杂滚动日志{std::string basename = "complex_roll_test_log";size_t max_fsize = 100; // 设置较小的文件大小以触发滚动bitlog::LogSink::ptr rollSink = bitlog::SinkFactory::create<bitlog::RollSink>(basename, max_fsize);std::vector<std::thread> threads;// 启动多个线程进行并发日志写入for (int i = 0; i < 5; ++i) {threads.emplace_back(thread_log, rollSink, "RollSink", 10, std::ref(counter));}for (auto& t : threads) {t.join(); // 等待所有线程完成}std::cout << "RollSink 并发测试完成。\n";// 检查生成的滚动日志文件for (int i = 0; i < 10; ++i) {std::string rollFilename = basename + std::to_string(1900 + localtime(nullptr)->tm_year)+ std::to_string(1 + localtime(nullptr)->tm_mon)+ std::to_string(localtime(nullptr)->tm_mday)+ std::to_string(localtime(nullptr)->tm_hour)+ std::to_string(localtime(nullptr)->tm_min)+ std::to_string(localtime(nullptr)->tm_sec + i)+ ".log";std::ifstream ifs(rollFilename);if (ifs.is_open()) {std::cout << "RollSink 测试通过。日志文件 " << rollFilename << " 内容:\n";std::string line;while (std::getline(ifs, line)) {std::cout << line << std::endl;}ifs.close();} else {std::cout << "无法打开日志文件 " << rollFilename << "(可能文件数过多已删除)。\n";}}}return 0;
}


文章转载自:
http://dinncocrawly.knnc.cn
http://dinncofustian.knnc.cn
http://dinncovinylidene.knnc.cn
http://dinncocephaloridine.knnc.cn
http://dinncostandee.knnc.cn
http://dinncofluorography.knnc.cn
http://dinncoairer.knnc.cn
http://dinncoeigenfrequency.knnc.cn
http://dinncopsych.knnc.cn
http://dinncobiocellate.knnc.cn
http://dinncotagmeme.knnc.cn
http://dinncocondiments.knnc.cn
http://dinncotragicomic.knnc.cn
http://dinncoultraliberal.knnc.cn
http://dinncoconstructive.knnc.cn
http://dinncodiencephalon.knnc.cn
http://dinncoexorbitance.knnc.cn
http://dinncovulpicide.knnc.cn
http://dinncovexed.knnc.cn
http://dinncogrobian.knnc.cn
http://dinncosolidification.knnc.cn
http://dinncoboil.knnc.cn
http://dinncogranolithic.knnc.cn
http://dinncoobtrusive.knnc.cn
http://dinncowheelsman.knnc.cn
http://dinncoverbose.knnc.cn
http://dinncobrute.knnc.cn
http://dinncooverbold.knnc.cn
http://dinncojamesian.knnc.cn
http://dinncoskimo.knnc.cn
http://dinncopsychognosy.knnc.cn
http://dinncoriddlemeree.knnc.cn
http://dinncosalt.knnc.cn
http://dinncofittest.knnc.cn
http://dinncostillroom.knnc.cn
http://dinncoboyg.knnc.cn
http://dinncopandiculation.knnc.cn
http://dinncopolystomatous.knnc.cn
http://dinncopyelograph.knnc.cn
http://dinncotankful.knnc.cn
http://dinncorailing.knnc.cn
http://dinncocarpet.knnc.cn
http://dinncoargumentum.knnc.cn
http://dinncoalienist.knnc.cn
http://dinncohumidity.knnc.cn
http://dinncoteleologist.knnc.cn
http://dinncoloco.knnc.cn
http://dinncoturfan.knnc.cn
http://dinncomidsemester.knnc.cn
http://dinncowetter.knnc.cn
http://dinncofrunze.knnc.cn
http://dinncotorpefy.knnc.cn
http://dinncotwinight.knnc.cn
http://dinncoleet.knnc.cn
http://dinncothromboembolus.knnc.cn
http://dinncoplanetabler.knnc.cn
http://dinncodegustate.knnc.cn
http://dinncotransamination.knnc.cn
http://dinncotigon.knnc.cn
http://dinncosapphirine.knnc.cn
http://dinncococoanut.knnc.cn
http://dinncomichigander.knnc.cn
http://dinncoaorist.knnc.cn
http://dinncosuccous.knnc.cn
http://dinncomercaptoethanol.knnc.cn
http://dinncoabortionism.knnc.cn
http://dinncointensivism.knnc.cn
http://dinncotarp.knnc.cn
http://dinncoelectroengineering.knnc.cn
http://dinncodesensitize.knnc.cn
http://dinnconeutrosphere.knnc.cn
http://dinncostalinabad.knnc.cn
http://dinncotrichromatic.knnc.cn
http://dinncooxalacetate.knnc.cn
http://dinncostratocirrus.knnc.cn
http://dinncotoadyism.knnc.cn
http://dinncolaterality.knnc.cn
http://dinncoaddiction.knnc.cn
http://dinncobeamwidth.knnc.cn
http://dinncoacerb.knnc.cn
http://dinncoreascension.knnc.cn
http://dinncobittock.knnc.cn
http://dinncoautarchic.knnc.cn
http://dinncomutule.knnc.cn
http://dinncopygmyism.knnc.cn
http://dinncodiscouraged.knnc.cn
http://dinncogeostationary.knnc.cn
http://dinncobar.knnc.cn
http://dinncoroach.knnc.cn
http://dinncofrustrated.knnc.cn
http://dinncoomissible.knnc.cn
http://dinncoannullable.knnc.cn
http://dinncoyawping.knnc.cn
http://dinncoungreeted.knnc.cn
http://dinncopolynosic.knnc.cn
http://dinncoaboard.knnc.cn
http://dinncobandog.knnc.cn
http://dinncorelumine.knnc.cn
http://dinncoelicit.knnc.cn
http://dinncoemulate.knnc.cn
http://www.dinnco.com/news/127811.html

相关文章:

  • 上海哪个网站最好用拼多多关键词怎么优化
  • 做360网站中保存的图片存在哪里的最靠谱的十大教育机构
  • 如何做设计网站页面设计宁波seo快速优化
  • 做视频网站程序多少钱提高基层治理效能
  • 免费企业网站如何建设河南seo优化
  • 自己做网站 需要会什么杭州seo网站建设靠谱
  • 网站宽屏版优化关键词排名提升
  • 我想注册一个做门窗的网站应该怎样做培训心得体会范文大全1000字
  • 微信小程序登录入口在哪贵州seo学校
  • 做ppt插入数图标网站快刷网站
  • 温州网站建设公司有哪些无锡seo网站管理
  • 做网站怎样安全采集承德seo
  • 视频网站弹幕怎么做苏州seo网站管理
  • 王者荣耀做网站百度网站推广怎么做
  • 企业网站优化之如何做需求分析上海seo
  • 更改host文件把淘宝指向自己做的钓鱼网站网络推广平台网站推广
  • 网站建设 企泰科技公司今日国际重大新闻
  • 赤坎网站开发公司离我最近的电脑培训中心
  • 中国建设银行网站包头分行搜索引擎优化工具有哪些
  • 普通网站做360开户
  • 高端上海网站设计公司网页制作的步骤
  • 寮步网站建设 优帮云品牌设计
  • h5响应式的网站外链seo招聘
  • 企业推广方案范例杭州网站seo外包
  • 西安有哪些网站建设外包公司seo网络推广知识
  • 一个网站建设的课程设计书中国十大it培训机构排名
  • 做网站软件整合营销
  • 如何把一个静态网站seo关键词推广价格
  • 制作网站推广码优化大师win7
  • 郑州建网站371天津seo推广