在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
使用两个缓存区存放日志,每个缓存区为一个hash表,通过线程id计算对应的hash值,将日志存入对应的位置。 一个log线程读取缓存区,并将其写入log文件,每次将两个缓存区更换,防止锁争用的开销,将缓冲区的日志写入文件后再次对换缓冲区,循环往复。 logger.h 1 #ifndef LOGGER_H 2 #define LOGGER_H 3 4 #include<fstream> 5 #include<sstream> 6 #include<iostream> 7 #include<vector> 8 9 #include<mutex> 10 #include<thread> 11 12 #include<sys/time.h> 13 14 #define ZLOG_INIT_SIZE 5 15 16 #define LOGERR ZLog::_ZLOG(ZLog::ZLogLeval::ERROR, __FILE__, __LINE__) 17 #define LOGINFO ZLog::_ZLOG(ZLog::ZLogLeval::INFO, __FILE__, __LINE__) 18 #define LOGWARN ZLog::_ZLOG(ZLog::ZLogLeval::WARRING, __FILE__, __LINE__) 19 #define LOGSTART(x) ZLog::SampleLogger::get()->start(x) 20 #define LOGSTOP() ZLog::SampleLogger::get()->stop() 21 22 namespace ZLog{ 23 24 enum ZLogLeval { 25 INFO, 26 WARRING, 27 ERROR 28 }; 29 extern char *ZLogLevalMsg[]; 30 31 32 class Logger 33 { 34 private: 35 int _size; 36 int now; 37 std::vector<std::string> *_buf[2]; 38 std::vector<std::mutex> *_mbuf[2]; 39 bool _stop = false; 40 private: 41 int _hash(); 42 public: 43 Logger(int size) ; 44 void add(std::string &info); 45 void logging(std::string logname); 46 void start(std::string logname); 47 void stop(); 48 ~Logger(); 49 }; 50 51 //Logger单例类 52 class SampleLogger{ 53 public: 54 static Logger *_logger; 55 static std::mutex m; 56 static Logger *get(); 57 }; 58 59 inline std::string getTime(void); 60 61 //LOG 操作类 重载<< 运算符 析构写日志 62 class _ZLOG 63 { 64 private: 65 std::string _info; 66 public: 67 _ZLOG(ZLogLeval leval, std::string file, int line); 68 _ZLOG &operator << (std::string info); 69 _ZLOG &operator << (int info); 70 _ZLOG &operator << (short); 71 _ZLOG &operator << (long); 72 _ZLOG &operator << (long long); 73 _ZLOG &operator << (char *); 74 _ZLOG &operator << (float); 75 _ZLOG &operator << (double); 76 _ZLOG &operator << (unsigned int); 77 _ZLOG &operator << (unsigned long); 78 _ZLOG &operator << (unsigned long long); 79 ~_ZLOG(); 80 }; 81 82 83 } 84 #endif logger.cpp #include "logger.h" namespace ZLog{ //TODO: 日志级别 char *ZLogLevalMsg[] = { "INFO", "WARRING", "ERROR" }; //TODO: 构造 Logger::Logger(int size = ZLOG_INIT_SIZE) : _size(size), now(0) { _buf[0] = new std::vector<std::string>(_size); _buf[1] = new std::vector<std::string>(_size); _mbuf[0] = new std::vector<std::mutex>(_size); _mbuf[1] = new std::vector<std::mutex>(_size); } // TODO: 添加日志 void Logger::add(std::string &info) { //计算线程hash int pos = this->_hash(); //加锁 std::lock_guard<std::mutex> lock(_mbuf[now]->at(pos)); //格式化日志 /* std::stringstream ss; try{ ss << "[ " << getTime() << " " << std::this_thread::get_id() << " " << __FILE__ << ":" << __LINE__ << " ]"; ss << "[ " << ZLogLevalMsg[leval] << " ] " << info; } catch (int e){ ss << "Call gettimeofday() error. Error code: "<< e; } ss << std::endl;*/ //添加到buf _buf[now]->at(pos) += info; } //TODO: 计算hash值 int Logger::_hash(){ auto tid = std::this_thread::get_id(); return *((__gthread_t *)&tid) % _size; } // TODO: 获取时间 inline std::string getTime(void) { timeval tv; tm * time; std::stringstream ss; if(gettimeofday(&tv, nullptr) == -1){ throw errno; } time = localtime(&(tv.tv_sec)); char systime[40]; strftime(systime, 40, "%Y-%m-%d %H:%M:%S.", time); ss << systime << (int64_t)(tv.tv_usec / 1000); return ss.str(); } //TODO: logger线程 void Logger::logging(std::string logname) { std::ofstream f(logname,std::ios::app); while(!_stop){ this->now = !this->now; for(int i= 0; i < this->_size; i++) { std::lock_guard<std::mutex> lock(_mbuf[!now]->at(i)); if(_buf[!now]->at(i).compare("")!=0) f << _buf[!now]->at(i) << std::endl; _buf[!now]->at(i) = ""; } f.flush(); } f.close(); } //TODO: 执行logging线程 void Logger::start(std::string logname){ this->_stop = false; std::thread t(&Logger::logging, this, logname); t.detach(); } //TODO: 关闭logging线程 void Logger::stop(){ this->_stop = true; } //TODO: 析构 Logger::~Logger(){ delete this->_buf[0]; delete this->_buf[1]; delete this->_mbuf[0]; delete this->_mbuf[1]; } //TODO: Logger单例类声明 Logger *SampleLogger::_logger = nullptr; std::mutex SampleLogger::m; Logger *SampleLogger::get(){ if(_logger == nullptr){ std::lock_guard<std::mutex> lock(m); if(_logger == nullptr){ _logger = new Logger(); } } return _logger; } //TODO: 初始化一个log _ZLOG::_ZLOG(ZLogLeval leval, std::string file, int line){ _info = ""; std::stringstream ss; try{ ss << "[" << getTime() << " " << std::this_thread::get_id() << " " << file << ":" << line << "]"; ss << "[" << ZLogLevalMsg[leval] << "] " ; } catch (int e){ ss << "Call gettimeofday() error. Error code: "<< e; } _info = ss.str(); } //TODO: ZLOG operator << _ZLOG &_ZLOG::operator << (std::string info){ _info += info; return *this; } _ZLOG &_ZLOG::operator << (int info){ _info += std::to_string(info); return *this; } _ZLOG &_ZLOG::operator << (short info){ _info += std::to_string(info); return *this; } _ZLOG &_ZLOG::operator << (long info){ _info += std::to_string(info); return *this; } _ZLOG &_ZLOG::operator << (long long info){ _info += std::to_string(info); return *this; } _ZLOG &_ZLOG::operator << (char * info){ _info += info; return *this; } _ZLOG &_ZLOG::operator << (float info){ _info += std::to_string(info); return *this; } _ZLOG &_ZLOG::operator << (double info){ _info += std::to_string(info); return *this; } _ZLOG &_ZLOG::operator << (unsigned int info){ _info += std::to_string(info); return *this; } _ZLOG &_ZLOG::operator << (unsigned long info){ _info += std::to_string(info); return *this; } _ZLOG &_ZLOG::operator << (unsigned long long info){ _info += std::to_string(info); return *this; } //TODO: ~_ZLOG() _ZLOG::~_ZLOG(){ _info += '\n'; SampleLogger::get()->add(_info); } }
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论