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

同步异步日志系统-日志落地模块的实现

功能:将格式化完成后的日志消息字符串,输出到指定的位置

扩展:支持同时将日志落地到不同的位置

位置分类:

1.标准输出

2.指定文件(时候进行日志分析)

3.滚动文件(文件按照时间/大小进行滚动切换)

扩展:支持落地方向的扩展

        用户可以自己编写一个新的落地模块,将日志进行其他方向的落地。

 实现思想

1.抽象出一个落地基类

2.之后根据落地方向从基类派生出不同落地方向的子类

3.使用工厂模式进行创建与表示分离

标准输出

class StdoutSink :public LogSink{public:void log(const char* data,size_t len)override{std::cout.write(data,len);}};

输入到指定文件

class FileSink :public LogSink{public://传入文件路径,并且打开文件FileSink(const std::string& pathname):_pathname(pathname){//创建日志文件所在的目录util::File::createDirectory(util::File::path(pathname));//创建并打开日志文件_ofs.open(_pathname,std::ios::binary|std::ios::app);assert(_ofs.is_open());//判断文件是否打开}//将日志消息输入到文件里面void log(const char* data,size_t len)override{_ofs.write(data,len);assert(_ofs.good());}private:std::string _pathname;std::ofstream _ofs;};

以大小进行滚动

class RollBySizeSink :public LogSink{public://传入文件路径,并且打开文件RollBySizeSink(const std::string& basename,size_t max_size):_basename(basename),_max_fsize(max_size),_cur_fsize(0){std::string pathname = createNewFile();//创建日志文件所在的目录util::File::createDirectory(util::File::path(pathname));//创建并打开日志文件_ofs.open(pathname,std::ios::binary|std::ios::app);assert(_ofs.is_open());//判断文件是否打开}//写入前判断文件大小,超过了最大大小就要切换文件void log(const char* data,size_t len)override{if(_cur_fsize>= _max_fsize){std::string pathname = createNewFile();_ofs.close();//关闭原来已经打开的文件。_ofs.open(pathname,std::ios::binary|std::ios::app);assert(_ofs.is_open());_cur_fsize = 0;}_ofs.write(data,len);assert(_ofs.good());_cur_fsize += len;}private:std::string createNewFile(){//获取系统时间,以时间来构造文件扩展名time_t t = util::Date::now();struct tm lt;localtime_r(&t,&lt);//将时间戳转换为有年月日的结构std::stringstream filename;filename << _basename;filename << lt.tm_year+1900;filename << lt.tm_mon+1;filename << lt.tm_mday;filename << lt.tm_hour;filename << lt.tm_min;filename << lt.tm_sec;filename << "-";filename <<_name_count++;filename << ".log";return filename.str();}//进行大小判断,超过指定大小就要切换新文件private://基础文件名+扩展文件名(时间生成)组成一个实际的当前输出文件名size_t _name_count=0;std::string _basename;std::ofstream _ofs;size_t _max_fsize;//记录最大大小,当前文件超过了这个大小就要切换文件size_t _cur_fsize;//记录当前文件已经写入的大小};

以时间进行滚动

enum class TimeGap{GAP_SECOND,GAP_MIUTE,GAP_HOUR,GAP_DAY,
};class RollByTimeSink :public bitlog::LogSink{public://传入文件路径,并且打开文件RollByTimeSink(const std::string& basename,TimeGap gap_type):_basename(basename){switch(gap_type){case TimeGap::GAP_SECOND:_gap_size = 1;break;case TimeGap::GAP_MIUTE:_gap_size = 60;break;case TimeGap::GAP_HOUR:_gap_size = 3600;break;case TimeGap::GAP_DAY:_gap_size = 3600*24;break;}_cur_gap = _gap_size == 1 ? bitlog::util::Date::now() : bitlog::util::Date::now() % _gap_size;std::string filename = createNewFile();//创建日志文件所在的目录bitlog::util::File::createDirectory(bitlog::util::File::path(filename));//创建并打开日志文件_ofs.open(filename,std::ios::binary|std::ios::app);assert(_ofs.is_open());//判断文件是否打开}//写入前判断文件大小,超过了最大大小就要切换文件void log(const char* data,size_t len)override{time_t cur =bitlog::util::Date::now();if((cur%_gap_size)!=_cur_gap){_ofs.close();std::string filename = createNewFile();_ofs.open(filename,std::ios::binary|std::ios::app);assert(_ofs.is_open());}_ofs.write(data,len);assert(_ofs.good());}private:std::string createNewFile(){//获取系统时间,以时间来构造文件扩展名time_t t = bitlog::util::Date::now();struct tm lt;localtime_r(&t,&lt);//将时间戳转换为有年月日的结构std::stringstream filename;filename << _basename;filename << lt.tm_year+1900;filename << lt.tm_mon+1;filename << lt.tm_mday;filename << lt.tm_hour;filename << lt.tm_min;filename << lt.tm_sec;filename << ".log";return filename.str();}//进行大小判断,超过指定大小就要切换新文件private:std::string _basename;std::ofstream _ofs;size_t _cur_gap;//当前是第几个时间段size_t _gap_size;//时间段的大小};

使用简易工厂模式来创建

class SinkFactory{public:template<typename SinkType,typename ...Args>static LogSink::ptr create(Args &&...args){return std::make_shared<SinkType>(std::forward<Args>(args)...);}};

http://www.lryc.cn/news/539284.html

相关文章:

  • LabVIEW 天然气水合物电声联合探测
  • 类型通配符上限
  • 嵌入式音视频开发(二)ffmpeg音视频同步
  • Mongodb数据管理
  • Django 创建表 choices的妙用:get_<field_name>_display()
  • Spring Boot 集成 Kettle
  • 自学Java-面向对象高级(final、单例类、枚举类、抽象类、接口)
  • Hutool - Cache:简单而强大的缓存实现
  • DeepSeek 通过 API 对接第三方客户端 告别“服务器繁忙”
  • Python 基础-循环
  • Java和SQL测试、性能监控中常用工具
  • SQL 注入攻击详解[基础篇]:Web 应用程序安全漏洞与防御策略
  • 【ArcGIS Pro二次开发】(87):样式_Style的用法
  • DEX-EE三指灵巧手:扩展AI与机器人研究的边界
  • 简站主题:简洁、实用、SEO友好、安全性高和后期易于维护的wordpress主题
  • 23种设计模式 - 责任链
  • Flink SQL与Doris实时数仓Join实战教程(理论+实例保姆级教程)
  • 算法——舞蹈链算法
  • 【复现DeepSeek-R1之Open R1实战】系列6:GRPO源码逐行深度解析(上)
  • 若依Flowable工作流版本监听器使用方法
  • 机器视觉--图像的运算(乘法)
  • 突破反爬困境:从服务端渲染到客户端SPA,爬虫环境的演变与新挑战(一)
  • matlab下载安装图文教程
  • 七、敏捷开发工具:持续集成与部署工具
  • 重看Spring聚焦BeanDefinition分析和构造
  • 2025年新型智慧城市整体解决方案下载:顶层规划设计,应用总体建设方案
  • 【旋转框目标检测】基于YOLO11/v8深度学习的遥感视角船只智能检测系统设计与实现【python源码+Pyqt5界面+数据集+训练代码】
  • 【物联网】电子电路基础知识
  • Linux-GlusterFS配置
  • IIS asp.net权限不足