美文网首页
Log日志系统

Log日志系统

作者: Bystander_1996 | 来源:发表于2019-11-05 11:04 被阅读0次

    实现和一个类似于glog的日志管理系统

    版本一:

    实现功能:将日志信息记录到两个文件中, 一个文件记录ERROR和WARNNING信息,一个文件记录INFO和DEBUG信息,在程序运行前指定要存储的文件的名称。

    //Logger.h
    
    #ifndef _LOGGER_H_
    #define _LOGGER_H_
    
    #include <iostream>
    #include <iomanip>
    #include <fstream>
    #include <string>
    #include <cstdlib>
    #include <stdint.h>
    
    typedef enum rank {
      ERROR,
      WARNNING,
      INFO,
      DEBUG
    }log_rank;
    
    void SetLogDestination(const std::string& ALL_LOG_FILENAME, const std::string& ERROR_AND_WARNING_FILENAME);
    
    class Logger {
        friend void SetLogDestination(const std::string& ALL_LOG_FILENAME, 
                               const std::string& ERROR_AND_WARNING_FILENAME);
      
    
      public:
    
        Logger() = delete;
        Logger(log_rank rank);
    
        ~Logger();
    
        static std::ostream& WriteLog(log_rank rank, 
                                   const int Line, 
                                   const std::string& Function, 
                                   const std::string& FileName);
    
      private:
    
        static std::ostream& GetStream (log_rank rank);
    
        static std::ofstream m_all_log_file;
        static std::ofstream m_error_and_warning_file;
        log_rank m_rank;
    
    };
    
    
    class Logger_P {
    
      public:
        Logger_P() = delete;
        Logger_P(log_rank rank);
    
        ~Logger_P();
    
        static std::ostream& ShowLog(log_rank rank,
                                     const int Line,
                                     const std::string& Function,
                                     const std::string& FileName);
      private:
        static std::ostream& GetStream(log_rank rank);
        log_rank m_rank;
    };
    
    #define LOG(rank)  \
        Logger(rank).WriteLog(rank, __LINE__, __FUNCTION__,  __FILE__)  
    
    #define LOG_P(rank) \
        Logger_P(rank).ShowLog(rank, __LINE__, __FUNCTION__, __FILE__)
    
    #endif  // _LOGGER_H_
    
    
    //logger.cpp
    
    #include <cstdlib>
    #include <ctime>
    #include <iostream>
    
    #include "logger.h"
    std::ofstream Logger::m_all_log_file;
    std::ofstream Logger::m_error_and_warning_file;
    
    void SetLogDestination(const std::string& ALL_LOG_FILENAME, const std::string& ERROR_AND_WARNING_FILENAME) {
    
        Logger::m_all_log_file.open(ALL_LOG_FILENAME.c_str(), std::ios::app);
        Logger::m_error_and_warning_file.open(ERROR_AND_WARNING_FILENAME.c_str(), std::ios::app );
    }
    
    std::ostream& Logger::GetStream (log_rank rank) {
        
        if (rank == ERROR or rank == WARNNING ) {
        
            if (m_error_and_warning_file.is_open())
                return m_error_and_warning_file;
            else 
                return std::cerr;
        }
        else if (rank == INFO or rank == DEBUG) { 
        
            if (m_all_log_file.is_open())
                return m_all_log_file;
            else 
                return std::cout;
        }
        else {
            std::cerr<< "Wrong Rank!!!"<< std::endl;
        }   
    }
    
    std::ostream& Logger::WriteLog(log_rank rank,
                                const int Line,
                                const std::string& Function,
                                const std::string& FileName) {
    
        time_t tm;
        time(&tm);
        char time_string[128];
        ctime_r(&tm, time_string);
        return Logger::GetStream(rank) << std::endl <<time_string 
                               << "File: <" << FileName << "> "
                               << " Function:  <" << Function << "> "
                               << " Line: " << Line << std::endl
                               << "LogMessage: "
                               << std::flush;
    
    }
    
    Logger::Logger(log_rank rank):m_rank(rank) { }
    
    Logger::~Logger() {
    
        Logger::GetStream(WARNNING) << std::endl << std::flush;
        Logger::GetStream(INFO) << std::endl<< std::flush;
        
     // m_all_log_file.close();
       // m_error_and_warning_file.close();
    
    }
    
    
    Logger_P::Logger_P(log_rank rank):m_rank(rank) {}
    
    Logger_P::~Logger_P() {std::cout << std::endl; }
    
    std::ostream& Logger_P::GetStream (log_rank rank) {
        
        if (rank == ERROR or rank == WARNNING)
            return std::cerr;
        else if (rank == INFO or rank == DEBUG)
            return std::cout;
        else 
            std::cerr << "Wrong Rank!!!" << std::endl;
    
    }
    
    std::ostream & Logger_P::ShowLog(log_rank rank,
                                          const int Line,
                                          const std::string& Function,
                                          const std::string& FileName) {
    
        time_t tm;
        time(&tm);
        char time_string[128];
        ctime_r(&tm, time_string);
        return Logger_P::GetStream(rank) << std::endl << time_string
                               << "File : <" << FileName << ">"
                               << " Function : <" << Function << ">"
                               << " Line : " << Line<< std::endl
                               << "LogMessage: " 
                               << std::ends;
    }
    
    //test.cpp
    
    #include <iostream>
    #include <string>
    #include "logger.h"
    int showwarning (){
        LOG_P(WARNNING)<< "WARNNING";
        LOG(WARNNING)<< "WARNNING";
        return 0;
    }
    
    int showerror () {
        LOG(ERROR)<< "there is something wrong!";
        LOG_P(ERROR)<< "there is something wrong!";
        return 0;
    }
    
    bool debug() {
        LOG(DEBUG)<< "BUG Need to be resolved!";
        LOG_P(DEBUG)<< "BUG Need to be resolved!";
        return true;
    }
    
    void showinfo() {
        LOG(INFO)<< "some info want to be record!";
        LOG_P(INFO)<< "some info want to be record!";
    }
    
    int main()
    {
        SetLogDestination("all.txt","error.txt");
        showwarning();
        showerror();
        debug();
        showinfo();
    
        return 0;
    }
    

    输出示例:

    LOP_P信息
    LOG记录信息

    版本二:

    需求变更:
    要求输出的log信息存储到两个文件中,一个文件用来存储ERROR和WARNNING信息,一个文件用来存储所有的log信息,并根据环境变量来决定记录到的等级,等级按ERROR,WARNNIGN,INFO,DEBUG排序,等级最低的时候只记录ERROR信息等级最高的时候记录所有的信息。并要求有多线程安全的机制。

    //logger.h
    
    #ifndef _LOGGER_H_
    #define _LOGGER_H_
    
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <array>
    #include <cstdlib>
    #include "spinlock.h"
    
    
    typedef enum rank {
      ERROR,
      WARNNING,
      INFO,
      DEBUG
    }log_rank;
    
    
    class Logger {
      public:
        static void SetLogPattern(const bool& to_screen, const bool& to_file);
      
        static Logger* GetInstance();
    
      public:
        ~Logger();//close file 
        Logger(const Logger&) = delete;
        Logger& operator = (const Logger&) = delete;
        void Record(log_rank rank, const int line, const std::string FileName,const std::string info);
    
      private:
        Logger();//open file 
        
        void StreamWriter (log_rank rank);
        void StoreInfo(const std::string info, const int line, const std::string filename);
        void InfoWriter(std::ostream &stream_out, log_rank rank);
    
      private:
        static bool out_to_screen_;
        static bool out_to_file_;
        std::ofstream logfile_;
        std::ofstream error_logfile_;
        std::string info_;
        int line_;
        std::string filename_;
        int  level_;
        log_rank rank_;
        libstream::SpinLock lock_;
        const std::array<std::string, 4> rank_arr_ = {"ERROR", "WARNNING", "ERROR", "DEBUG"};
    };
    
    
    #define LOG(rank, string)  \
        Logger::GetInstance()->Record(rank, __LINE__, __FILE__,string);  
    
    
    #endif  // _LOGGER_H_
    
    
    //logger.cpp
    
    #include <cstdlib>
    #include <ctime>
    #include <iostream>
    #include <string>
    #include "logger.h"
    
    
    bool Logger::out_to_file_ = 1;
    bool Logger::out_to_screen_ = 1;
    
    void Logger::SetLogPattern(const bool& to_screen, const bool& to_file) {
        Logger::out_to_screen_ = to_screen;
        Logger::out_to_file_ = to_file;
    }
    
    Logger* Logger::GetInstance() {
        static Logger instance;
        return &instance;
    }
    
    
    void Logger::StoreInfo(const std::string info, const int line, const std::string filename) {
        info_ = info;
        line_ = line;
        filename_ = filename;
    }
    
    void Logger::InfoWriter(std::ostream &stream_out, log_rank rank) {
        time_t tm;
        time(&tm);
        char time_string[128];
        strftime(time_string, 128, "%Y %m.%d %T", localtime(&tm));
        std::string str_time (time_string);
        stream_out << str_time
                << "  File : " << filename_
                << "  Line : " << line_ 
                << "  [" << rank_arr_[rank]<< "] "
                << info_
                << std::endl;
    }
    
    
    void Logger::StreamWriter (log_rank rank) {
        if (rank == ERROR or rank == WARNNING) {
          if (out_to_file_) {
            InfoWriter(error_logfile_, rank);
            InfoWriter(logfile_, rank);
        }
          if (out_to_screen_)
            InfoWriter(std::cerr, rank);
        }
        else if (rank == INFO or rank == DEBUG) {
          if (out_to_file_)
            InfoWriter(logfile_,rank);
          if (out_to_screen_)
            InfoWriter(std::cout, rank);
        }
        else
          std::cout << "Wrong rank!!!"<<std::endl;
    }
    
    void Logger::Record(log_rank rank,
                        const int line,
                        const std::string filename,
                        const std::string info) {
    
        StoreInfo(info, line, filename);
    
        libstream::SpinLockGuard lk(lock_);
        switch (level_) {
          case 3:
            if(rank == DEBUG) 
              StreamWriter(DEBUG);
          case 2:
            if (rank == INFO) 
              StreamWriter(INFO);
          case 1:
            if (rank == WARNNING)
              StreamWriter(WARNNING);
          case 0:
            if (rank == ERROR)
              StreamWriter(ERROR);
    }
    }
    
    // open file 
    Logger::Logger() {
        char * level = getenv("LEVEL");
        if (level == nullptr)
            level_ = 1;
        else{
            level_ = level[0] - '0';
            if (level_ <0 or level_>3){
                std::cerr << "The CNSTREAM_TOOLKIT_LOG_LEVEL must have a value between 0 and 5"<< std::endl;
                level_ = 1;
            }
        }
    
        time_t tm;
        time(&tm);
        char time_string[128];
        strftime(time_string, 128, "Logfile_%Y-%m.%d-%T", localtime(&tm));
        std::string str_name(time_string);
        logfile_.open((str_name + ".log").c_str());
        error_logfile_.open((str_name + "_error.log").c_str());
    }
    
    //close file 
    Logger::~Logger() {
        logfile_.close();
        error_logfile_.close();
    }
    
    //spinlock.h
    
    #ifndef SPIN_LOCK_H_
    #define SPIN_LOCK_H_
    
    #include <atomic>
    
    class SpinLock {
     public:
      void lock() {
        while (lock_.test_and_set(std::memory_order_acquire)) {
        }
      }
      void unlock() { lock_.clear(std::memory_order_release); }
    
     private:
      std::atomic_flag lock_ = ATOMIC_FLAG_INIT;
    };
    
    class SpinLockGuard {
     public:
      explicit SpinLockGuard(SpinLock &lock) : lock_(lock) { lock_.lock(); }
      ~SpinLockGuard() { lock_.unlock(); }
    
     private:
      SpinLock &lock_;
    };
    
    #endif  // SPIN_LOCK_H_
    
    //test.cpp
    
    
    #include <iostream>
    #include <string>
    #include "logger.h"
    int showwarning (){
        LOG(WARNNING, "WARNNING");
        return 0;
    }
    
    int showerror () {
        LOG(ERROR, "there is something wrong!");
        return 0;
    }
    
    bool debug() {
        LOG(DEBUG, "BUG Need to be resolved!");
        return true;
    }
    
    void showinfo() {
        LOG(INFO, "some info want to be record!");
    }
    
    int main()
    {
        Logger::SetLogPattern(0,1);
        showwarning();
        showerror();
        debug();
        showinfo();
    
        return 0;
    }
    
    

    注:SetLogPattern(param1,param2)
    param1:决定是否将日志信息以jcout或cerr的形式输出到屏幕
    param2:决定是否将日志信息记录到文件中

    编译运行:

    编译运行

    注:LEVEL是给定环境变量:根据环境变量决定打印的等级:
    LEVEL =0 : 只输出ERROR信息
    LEVEL =1 : 输出ERROE和WARNNING信息
    LEVEL =2 : 输出ERROR,WARNNING和INFO信息
    LEVEL =3 : 输出ERROR,WARNNING,INFO和DEBUG信息

    运行结果:

    生成文件 记录信息

    相关文章

      网友评论

          本文标题:Log日志系统

          本文链接:https://www.haomeiwen.com/subject/klqsbctx.html