用C++實現一個Log系統 -電腦資料

用C++實現一個Log系統 -電腦資料

日期:2023-03-09 14:46:48    编辑:网络投稿    来源:网络资源

用C++實現一個Log系統 -電腦資料 電腦資料 時間:2019-01-01 我要投稿 【w
用C++實現一個Log系統 -電腦資料 電腦資料 時間:2019-01-01 我要投稿 【www.unjs.com - 電腦資料】

提要

最近在寫一些C++的圖形代碼,在調試和測試過程中都會需要在終端打印一些信息出來,用C++實現一個Log系統。之前的做法是直接用

std::cout<<some pre=""></p><p> 這樣做其實非常的麻煩,每次都要打很多的字母還有特殊符號,除去我要打印的內容,還需要按下28下鍵盤,簡直不能忍!</p><p> 參考Unity里面的打log的方式</p>

或者Qt中的處理方式

qDebug() << Some Word;

這兩種都方便太多。

今天要實現的Log系統需要滿足的特性有:

1.很方便地在終端打印各種類型數據信息;

2.可以區分Log等級;

3.打印信息的同時能夠提供打印語句的文件,函數名,行號

類說明

簡單地畫了下UML,主要分為下面幾個類

簡單說一下類的作用

MessageLogContext

記錄Log的上下文,也就是Log處在的文件,函數名,行號。

MessageLogger

主要的Log類,提供了上次調用的一些接口,注意一下這個宏比較有意思

qDebug MessageLogger(__FILE__, __FUNCTION__, __LINE__).debug

這樣當使用

qDebug()

的時候,

宏替換就直接轉換成了MessageLogger的構造函數

MessageLogger(__FILE__, __FUNCTION__, __LINE__).debug()

等于是先構造MessageLogger,然后調用這個對象的debug()方法。

Debug

具體處理Debug信息的類。

用了一個內部Stream結構體來記錄Debug信息,記得在使用前要new,析構的時候delete掉。

重構了很多的<<方法,就是為了能處理多種數據類型,包括自定義的類。還可以通過模板來打印stl里面的東西。

LogToConsole是將log信息打印到終端的函數,在析構函數中會被調用。如果想要實現更加炫酷的打印log方式(各種顏色),擴展這個函數就好了。

整個Log的流程如下圖

測試代碼

void DebugTest(){Vector2 v = Vector2(1, 1);Vector2 v2 = Vector2(2, 1);Vector3 v3 = Vector3(0, 2, 1);Vector3 v4 = Vector3(0, 2, 1);Vector3 v5 = Vector3(23, 112, 22);Vector3 v6 = Vector3(23, 112, 22);std::vector<vector3>vec;vec.push_back(v3);vec.push_back(v4);vec.push_back(v5);vec.push_back(v6);vec.push_back(v6);vec.push_back(v6);vec.push_back(v6);vec.push_back(v6);std::string testStr = vector Test;qDebug() << Hello Debug;qDebug() <<<< v << v2<< v3;qDebug() << v3;qWarning() << vec;}</vector3>

運行結果

代碼清單MessageLogContext.h

#pragma once#include<string>class MessageLogContext{public:MessageLogContext() : line(0), file(0), function(0) {}MessageLogContext(const char *fileName, const char *functionName, int lineNumber): file(fileName), function(functionName), line(lineNumber) {}int line;const char *file;const char *function;void copy(const MessageLogContext &logContext){this->file = logContext.file;this->line = logContext.line;this->function = logContext.function;}private:friend class MessageLogger;friend class Debug;};</string>

Log.h#pragma once#define qDebug MessageLogger(__FILE__, __FUNCTION__, __LINE__).debug#define qInfo MessageLogger(__FILE__, __FUNCTION__, __LINE__).info#define qWarning MessageLogger(__FILE__, __FUNCTION__, __LINE__).warning#define qCritical MessageLogger(__FILE__, __FUNCTION__, __LINE__).critical#define qFatal MessageLogger(__FILE__, __FUNCTION__, __LINE__).fatal#include Debug.h#include MessageLogContext.hclass MessageLogger{public:MessageLogger() : context(){}MessageLogger(const char *fileName, const char *functionName, int lineNumber): context(fileName, functionName, lineNumber) {}Debug info() const;Debug warning() const;Debug critical() const;Debug debug() const;protected:private:MessageLogContext context;};

Log.cpp

#include Log.hDebug MessageLogger::debug() const{std::string debug = debug;Debug dbg = Debug(&debug);MessageLogContext &ctxt = dbg.stream->context;ctxt.copy(context);dbg.stream->logType = Info;return dbg;}Debug MessageLogger::info() const{Debug dbg = Debug();MessageLogContext &ctxt = dbg.stream->context;ctxt.copy(context);dbg.stream->logType = Info;return dbg;}Debug MessageLogger::warning() const{Debug dbg = Debug();MessageLogContext &ctxt = dbg.stream->context;ctxt.copy(context);dbg.stream->logType = Warning;return dbg;}Debug MessageLogger::critical() const{Debug dbg = Debug();MessageLogContext &ctxt = dbg.stream->context;ctxt.copy(context);dbg.stream->logType = Error;return dbg;}

Debug.h#pragma once#include<iostream>#include<iomanip>#include<fstream>#include<string>#include<cstdlib>#include<stdint.h>#include<sstream>#include Math/Vector2.h #include Math/Vector3.h #include<vector>//#include Log.h#include MessageLogContext.henum LogType{Info,Warning,Error,Default,};class Debug{public:struct Stream {Stream():ss(), space(true), context() {}Stream(std::string *s) :ss(*s), space(true), context(){}std::ostringstream ss;bool space;MessageLogContext context;LogType logType;} *stream;Debug() : stream(new Stream()) {}inline Debug(std::string *s) : stream(new Stream(s)) {}~Debug();inline Debug &operator<<(bool t) { stream->ss<<(t ? true : false); return maybeSpace(); }inline Debug &operator<<(char t) { stream->ss<< t; return maybeSpace(); }inline Debug &operator<<(signed short t) { stream->ss << t; return maybeSpace(); }inline Debug &operator<<(unsigned short t) { stream->ss << t; return maybeSpace(); }inline Debug &operator<<(std::string s) { stream->ss << s; return maybeSpace(); }inline Debug &operator<<(const char* c) { stream->ss << c; return maybeSpace(); }inline Debug &operator<<(Vector2 vec) { stream->ss << ( << vec.x <<,<< vec.y<<); return maybeSpace(); }inline Debug &operator<<(Vector3 vec) { stream->ss << ( << vec.x << , << vec.y <<, << vec.z << ); return maybeSpace(); }inline Debug &space() { stream->space = true; stream->ss << ' '; return *this; }inline Debug &nospace() { stream->space = false; return *this; }inline Debug &maybeSpace() { if (stream->space) stream->ss << ' '; return *this; }template<typename t="">inline Debug &operator<<(const std::vector<t>&vec){stream->ss << '(';for (int i = 0; i < vec.size(); ++i) {stream->ss << vec.at(i);stream->ss << , ;}stream->ss << ')';return maybeSpace();}void LogToConsole(LogType type, const MessageLogContext &context, std::string logBuffer);private:static Debug* _instance;};</t></typename></vector></sstream></stdint.h></cstdlib></string></fstream></iomanip></iostream>

Debug.cpp#include Debug.hDebug::~Debug(){LogToConsole(stream->logType, stream->context, stream->ss.str());delete stream;}void Debug::LogToConsole(LogType type, const MessageLogContext &context, std::string logBuffer){std::string logString;switch (type){case Error:logString.append(Error! );break;case Info://logString.append();break;case Warning:logString.append(Warning! );break;default:break;}logString.append(logBuffer);logString.append(......);logString.append(context.file);logString.append( );logString.append(context.function);logString.append(());std::cout << logString << line: << context.line << << std::endl;//logString.append(context.line);}