一个基于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 += '\n';
        SampleLogger::get()->add(_info);
    }

}

 

原文链接: https://www.cnblogs.com/HadesBlog/p/13154578.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    一个基于c++的log库

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/356313

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午11:09
下一篇 2023年3月2日 上午11:09

相关推荐