用C++实现一个Log系统
来源:互联网 发布:iphone pro画笔软件 编辑:程序博客网 时间:2024/06/03 16:59
提要
最近在写一些C++的图形代码,在调试和测试过程中都会需要在终端打印一些信息出来。之前的做法是直接用
std::cout<<"Some Word"<<std::endl;
这样做其实非常的麻烦,每次都要打很多的字母还有特殊符号,除去我要打印的内容,还需要按下28下键盘,简直不能忍!
参考Unity里面的打log的方式
Debug.Log("Some Word");
或者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;}
运行结果
代码清单
#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;};
#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.h"class 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;};
#include "Log.h"Debug 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;}
#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.h"enum 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;};
#include "Debug.h"Debug::~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);}
参考
Qt source code
Qt Documentation http://doc.qt.io/qt-4.8/qdebug.html
http://www.cplusplus.com/
- 用C++实现一个Log系统
- 一个同步日志系统的简单实现 log for c (linux 平台)
- C语言实现一个学生信息管理系统
- 简单log系统的实现
- C实现 log n(m)
- C风格简易本地log系统
- 一个写log的函数 log_func.c
- 一个写log的函数 log_func.c .
- 广告系统中广告实现log
- python实现的系统实用log类
- Android 系统log抓取,实现原理分析
- C++实现简易log日志系统
- 实现一个基于xml的log类
- go: 一个通用log模块的实现
- 一个简单明了的c++ trace log 实现
- 歌厅歌曲管理系统(转)用c语言实现的一个课程设计
- 如何实现一个c/s模式的flv视频点播系统
- C++: 实现一个简易的银行排号叫号系统
- centos6.5 64位 搭建FTP服务器
- VMWare下桥接模式上网设置
- Filter及FilterChain的使用详解以及servlet、filter、listener 区别
- C++及Windows异常处理(try,catch; __try,__finally; __try, __except) ----一道笔试题引起的探究
- 怀疑博客被XSS(Cross Site Scripting)
- 用C++实现一个Log系统
- Android中BroadCastReceiver使用(整理)
- LeetCode 202:Happy Number
- 用百度编辑器发布新闻(UEditor的初始化开发部署)
- [脑洞] 将机器学习运用到计算机储存图像上?
- android-Making Applications Accessible
- 随笔
- 内存泄露从入门到精通三部曲之常见原因与用户实践
- JAVA并发编程笔记一