日志系统——落地模块

avatar
作者
筋斗云
阅读量:0

一条日志可以输出到显示屏,也可以输出到指定文件,更灵活一点可以根据文件大小和日志时间自动设置输出目的,将这种想法落实于代码中,就需要定义各个类表示不同落地方向,再有一个抽象落地基类进行统一调用方法

日志落地类

抽象基类

  class LogLand   //使用land命名空间进行限定    {    public:        virtual ~LogLand() {}        virtual void landing(const char *data, size_t len) = 0;    }; 

landing方法是一个需要被派生类重写的函数,每一个派生类都通过landing方法进行日志消息的输出
标准输出落地类

   class StdoutLogLand : public LogLand    {    public:        virtual void landing(const char *data, size_t len) override        {        		std::cout.write(data, len); //避免使用<<进行输出,因为<<遇到\0会终止,write更加安全        }    }; 

指定文件落地类

class FileLogLand : public LogLand { private:    std::ofstream _file;    std::string _filename; public:    FileLogLand(const char *file): _filename(file) 	{     util::File::createDirectory(util::File::path(file)); // 创建文件所在目录     _file.open(_filename, std::ios::app | std::ios::binary);     assert(_file.is_open()); 	}    virtual void landing(const char *data, size_t len) override    { 	_file.write(data, len); 	assert(_file.good()); // 检查是否写入发生错误    } }; 

用户传入的文件路径可能不存在,需要在构造函数中进行判断,如果不存在则创建
滚动文件落地类(按文件大小、按日志时间)

   class ScrollBySizeLogLand : public LogLand    {    private:        size_t _name_cnt = 0; //防止1s之内创建多文件 ,可能在极端情况下1s之内就已经写满了一个文件,再次创建一个文件会导致文件名冲突        std::ofstream _file;        std::string _basename; //每一次生成的文件名格式为basename+时间信息(最小单位为秒)        size_t _max_size; //文件大小上限        size_t _cur_size = 0; //当前文件大小    public:        ScrollBySizeLogLand(const char *file, size_t maxsize = 1024 * 1024 * 1024); // 默认最大为1G        virtual void landing(const char *data, size_t len) override;    private:        std::string setFilename();    };     class ScrollByTimeLogLand : public LogLand    {    private:        time_t _time_gap; //表示每过一个time_gap秒数就切换一个文件        time_t _cur_gap;        std::ofstream _file;        std::string _basename;    public:        enum struct TimeGap        {            SECOND = 1,            MINUTE = 60,            HOUR = 3600,            DAT = 3600 * 24        };        ScrollByTimeLogLand(const char *file, TimeGap gap);        virtual void landing(const char *data, size_t len) override;    private:        std::string setFilename();    }; 

滚动文件方法实现:

land::ScrollBySizeLogLand::ScrollBySizeLogLand(const char *file, size_t maxsize)     : _basename(file), _max_size(maxsize) {     util::File::createDirectory(util::File::path(file));     // 创建文件所在目录+创建文件     _file.open(_basename + setFilename(), std::ios::binary | std::ios::app);     assert(_file.is_open()); } std::string land::ScrollBySizeLogLand::setFilename() {     std::stringstream ss;     time_t timestamp = util::Date::getTime();     struct tm *t = localtime(&timestamp);     ss << t->tm_year + 1900;     ss << t->tm_mon + 1;     ss << t->tm_mday;     ss << t->tm_hour;     ss << t->tm_min;     ss << t->tm_sec;     ss << "-" + std::to_string(_name_cnt++) + ".log";     return ss.str(); } void land::ScrollBySizeLogLand::landing(const char *data, size_t len) {     if (_cur_size >= _max_size)     {         _file.close(); //! 关闭原来的文件         _cur_size = 0; //! 归置_cur_size         _file.open(_basename + setFilename(), std::ios::app | std::ios::binary);         assert(_file.is_open());     }     _file.write(data, len);     assert(_file.good());     _cur_size += len; }  land::ScrollByTimeLogLand::ScrollByTimeLogLand(const char *file, TimeGap gap)     : _basename(file), _time_gap((time_t)gap) {     _cur_gap = util::Date::getTime();     util::File::createDirectory(util::File::path(file));     _file.open(_basename + setFilename(), std::ios::binary | std::ios::app);     assert(_file.is_open()); } void land::ScrollByTimeLogLand::landing(const char *data, size_t len) {     if (_cur_gap + _time_gap == util::Date::getTime())     {         _cur_gap += _time_gap;         _file.close();         _file.open(_basename + setFilename(), std::ios::binary | std::ios::app);         assert(_file.is_open());     }     _file.write(data, len);     assert(_file.good()); }  std::string land::ScrollByTimeLogLand::setFilename() {     std::stringstream ss;     time_t timestamp = util::Date::getTime();     struct tm *t = localtime(&timestamp);     ss << t->tm_year + 1900;     ss << t->tm_mon + 1;     ss << t->tm_mday;     ss << t->tm_hour;     ss << t->tm_min;     ss << t->tm_sec;     ss << "-.log";     return ss.str(); } 

    广告一刻

    为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!