C++ 實現一個日志類


轉載:https://blog.csdn.net/baidu_41743195/article/details/107359665

我們可能遇到發包后,在客戶機器上出現各種未知錯誤,如果沒有日志打印,對於問題解決是很困難的,因此常規的解決辦法就是打印日志。

在此用C++ 實現一個簡單的日志類,使用cout輸出調試信息,同時把日志寫到文件中,實現了一個Logger類,主要考慮實現以下功能:

  • 日志等級: 參考python的logger類,我設置了四個日志等級, 從低到高依次為debug, info, warning, error,這樣的話我想輸出一條debug信息就可以這樣寫logger.debug("something..."), (關於日志等級是什么意思可以參考一下python的logger類,簡單來說就是當日志等級大於等於設置的初始等級時才會記錄日志)
  • 輸出目標: 我設置了三種輸出目標: 僅輸出到終端、僅輸出到文件、既輸出到終端又輸出到文件

為了方便的設置日志等級,可以用一個枚舉類表示四種日志等級,同理用一個枚舉類表示三種輸出目標

enum log_level{debug, info, warning, error};// 日志等級
enum log_target{file, terminal, file_and_terminal};// 日志輸出目標

Logger.h

#ifndef _LOGGER_H_
#define _LOGGER_H_

#include <iostream>
#include <fstream>
#include <time.h>

#pragma warning (disable:4996)

class Logger
{
public:
    enum log_level { debug, info, warning, error };// 日志等級
    enum log_target { file, terminal, file_and_terminal };// 日志輸出目標
public:
    Logger();
    Logger(log_target target, log_level level, const std::string& path);
    ~Logger();
    
    void DEBUG(const std::string& text);
    void INFO(const std::string& text);
    void WARNING(const std::string& text);
    void ERRORS(const std::string& text);

private:
    std::ofstream m_outfile;    // 將日志輸出到文件的流對象
    log_target m_target;        // 日志輸出目標
    std::string m_path;              // 日志文件路徑
    log_level m_level;          // 日志等級
    void output(const std::string &text, log_level act_level);            // 輸出行為
};

#endif//_LOGGER_H_

Logger.cpp

#include "Logger.h"
#include <string>

std::string currTime()
{
    // 獲取當前時間,並規范表示
    char tmp[64];
    time_t ptime;
    time(&ptime);  // time_t time (time_t* timer);
    strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S", localtime(&ptime));
    return tmp;
}

Logger::Logger()
{
    // 默認構造函數
    m_target = terminal;
    m_level = debug;
    std::cout << /*"[WELCOME] " << __FILE__ << " " <<*/ currTime() << " : " << "=== Start logging ===" << std::endl;
}


Logger::Logger(log_target target, log_level level, const std::string& path)
{
    m_target = target;
    m_path = path;
    m_level = level;

    std::string strContent =   currTime() + " : " + "=== Start logging ===\n";
    if (target != terminal) {
        m_outfile.open(path, std::ios::out | std::ios::app);   // 打開輸出文件
        m_outfile << strContent;
    }
    if (target != file) 
    {
        // 如果日志對象不是僅文件
        std::cout << strContent;
    }
}

Logger::~Logger()
{
    std::string  strContent =  currTime() + " : " + "=== End logging ===\r\n";
    if (m_outfile.is_open())
    {
        m_outfile << strContent;
    }
    m_outfile.flush();
    m_outfile.close();
}

void Logger::DEBUG(const std::string& text)
{
    output(text, debug);
}

void Logger::INFO(const std::string& text)
{
    output(text, info);
}

void Logger::WARNING(const std::string& text)
{
    output(text, warning);
}

void Logger::ERRORS(const std::string& text)
{
    output(text, error);
}

void Logger::output(const std::string &text, log_level act_level)
{
    std::string prefix;
    if (act_level == debug) prefix = "[DEBUG] ";
    else if (act_level == info) prefix = "[INFO] ";
    else if (act_level == warning) prefix = "[WARNING] ";
    else if (act_level == error) prefix = "[ERROR] ";
    //else prefix = "";
    //prefix += __FILE__;
    //prefix += " ";
    std::string outputContent = prefix + currTime() + " : " + text + "\n";
    if (m_level <= act_level && m_target != file) 
    {
        // 當前等級設定的等級才會顯示在終端,且不能是只文件模式
        std::cout << outputContent;
    }
    if (m_target != terminal)
        m_outfile << outputContent;

    m_outfile.flush();//刷新緩沖區
}

測試

#include "Logger.h"

void test() {
    Logger logger(Logger::file_and_terminal, Logger::debug, "Log.log");
    logger.DEBUG("Debug info");
    logger.INFO("This is variable");
    logger.WARNING("This function or variable may be unsafe");
    logger.ERRORS("Memory leak");
}

int main()
{
    test();
    getchar();
    return 0;
}

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM