主页 > IT业界  > 

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

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

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

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

位置分类:

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)...); } };

标签:

同步异步日志系统-日志落地模块的实现由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“同步异步日志系统-日志落地模块的实现