轉載: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; }