美文网首页
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