用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);}

   

最新文章