zoukankan      html  css  js  c++  java
  • 一个基于c++的log库

    使用两个缓存区存放日志,每个缓存区为一个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 += '
    ';
            SampleLogger::get()->add(_info);
        }
    
    }
  • 相关阅读:
    RubyConf的podcast
    一篇很好的英语学习文章:一个孤独而封闭世界――英语口语
    新浪和搜狐的读书频道
    新想法:个性化的RSS
    代码搜索:Koders
    我看到的Web 2.0: 自组织的大众化参与
    土豆网的后舍男孩挺搞笑的
    可以给pdf加批注的软件VeryPDF PDF Editor
    张海迪写的描写英语学习经验的书《美丽的英语》
    Fowler出来推荐Rake了(基于Ruby的build工具)
  • 原文地址:https://www.cnblogs.com/HadesBlog/p/13154578.html
Copyright © 2011-2022 走看看