简易版Log日志可参考:https://blog.csdn.net/qq135595696/article/details/127467597
下面进阶版,将原本的全局日志方法封装为类,通过运算符重载来使用日志,更加便捷。
#pragma once
#include
#include
#include
namespace U {
enum class LOG_LEVEL {
LOG_TRACE_LEVEL = 0, //用于流程跟踪
LOG_DEBUG_LEVEL, //用于输出调试信息(debug)
LOG_INFO_LEVEL, //用于输出反馈信息(release)
LOG_WARN_LEVEL, //用于输出警告
LOG_ERROR_LEVEL, //用于输出错误
LOG_FATAL_LEVEL, //用于输出严重错误
LOG_SYSERR_LEVEL, //用于输出系统错误
LOG_SYSFATAL_LEVEL, //用于输出系统文件错误
LOG_LEVELS
};
class LogBuf {
public:
LogBuf();
~LogBuf();
bool Init(int len = 4096);
bool UnInit();
void Release();
uint32_t GetLen();
const char* GetBuf();
bool Append(const char* buf, uint32_t len);
char* GetCurAvailBuf();
bool AddLen(uint32_t len);
bool HandleExpandMemory(uint32_t len);
private:
uint32_t _GetAvail() const;
private:
char* m_buf;
uint32_t m_nowLen;
uint32_t m_maxLen;
};
class ILogger {
public:
//线程不安全,会在多个线程中调用
virtual bool OutPut(U::LOG_LEVEL level, U::LogBuf* buf) = 0;
};
class CLogger {
public:
~CLogger();
static bool SetLogger(ILogger* pLogger);
static ILogger* GetLogger();
static bool SetLevel(LOG_LEVEL level);
static LOG_LEVEL GetLevel();
public:
template<int N>
CLogger(const char(&pFunc)[N], int line, U::LOG_LEVEL level) {
static const char* s_LogLevelName[(int)LOG_LEVEL::LOG_LEVELS] = {
"TRACE",
"DEBUG",
"INFO",
"WARN",
"ERROR",
"FATAL",
"SYSERR",
"SYSFATAL"
};
char ch[64];
size_t nRet;
#ifdef _WIN32
//windows系统
__time64_t longTime;
struct tm time;
_time64(&longTime);
_localtime64_s(&time, &longTime);
nRet = sprintf_s(ch, sizeof(ch), "%d-%d-%d %d:%d:%02d",
time.tm_year + 1900, time.tm_mon + 1, time.tm_mday,
time.tm_hour, time.tm_min, time.tm_sec);
#else
//其他系统
time_t = time(0);
nRet = strftime(ch, sizeof(ch), "%Y-%m-%d %H:%M:%S",
localtime(&time));
#endif
//时间
ms_buf.Append(ch, (uint32_t)nRet);
ms_buf.Append(" ", 1);
//日志等级
ms_buf.Append("[LogType: ", 10);
*this << s_LogLevelName[(int)level];
ms_buf.Append("] ", 2);
//函数名
ms_buf.Append("[Func: ", 7);
ms_buf.Append(pFunc, N - 1);
ms_buf.Append("] ", 2);
//行号
ms_buf.Append("[Line: ", 7);
*this << line;
ms_buf.Append("] ", 2);
}
CLogger& operator<<(const char* pBuf);
CLogger& operator<<(int value);
CLogger& operator<<(uint64_t value);
CLogger& operator<<(const unsigned char* pBuf);
CLogger& operator<<(std::string& buf);
CLogger& operator<<(const std::string& buf);
CLogger& operator<<(unsigned int value);
CLogger& operator<<(bool b);
CLogger& operator<<(const void* p);
private:
template<typename T>
bool _FormateInterger(T value) {
ms_buf.HandleExpandMemory(32);
size_t len = _Convert(ms_buf.GetCurAvailBuf(), value);
ms_buf.AddLen(len);
return true;
}
template<typename T>
size_t _Convert(char* buf, T value) {
static const char s_digits[] = "9876543210123456789";
static const char* s_zero = s_digits + 9;
T i = value;
char* p = buf;
do {
int odd = static_cast<int>(i % 10);
i /= 10;
*p++ = s_zero[odd];
} while (i != 0);
if (value < 0) {
*p++ = '-';
}
*p = '\0';
std::reverse(buf, p);
return p - buf;
}
size_t _ConvertHex(char* buf, uintptr_t value);
private:
static LogBuf ms_buf;
};
#define LOG____(level) \
if(U::CLogger::GetLogger() != nullptr) \
U::CLogger(__FUNCTION__, __LINE__, level)
// 用于流程跟踪
#define LOG_TRACE \
if(U::CLogger::GetLevel() <= U::LOG_LEVEL::LOG_TRACE_LEVEL) \
LOG____(U::LOG_LEVEL::LOG_TRACE_LEVEL)
// 用于输出调试信息
#define LOG_DEBUG \
if(U::CLogger::GetLevel() <= U::LOG_LEVEL::LOG_DEBUG_LEVEL) \
LOG____(U::LOG_LEVEL::LOG_DEBUG_LEVEL)
// 用于输出反馈信息
#define LOG_INFO \
if(U::CLogger::GetLevel() <= U::LOG_LEVEL::LOG_INFO_LEVEL) \
LOG____(U::LOG_LEVEL::LOG_INFO_LEVEL)
// 警告
#define LOG_WARN LOG____(U::LOG_LEVEL::LOG_WARN_LEVEL)
// 错误
#define LOG_ERROR LOG____(U::LOG_LEVEL::LOG_ERROR_LEVEL)
// 严重错误
#define LOG_FATAL LOG____(U::LOG_LEVEL::LOG_FATAL_LEVEL)
// 系统错误
#define LOG_SYSERR LOG____(U::LOG_LEVEL::LOG_SYSERR_LEVEL)
// 系统文件
#define LOG_SYSFATAL LOG____(U::LOG_LEVEL::LOG_SYSFATAL_LEVEL)
}
#include "Logger.h"
static U::ILogger* gs_pLogger = nullptr;
static U::LOG_LEVEL gs_eLevel = U::LOG_LEVEL::LOG_TRACE_LEVEL;
namespace U {
LogBuf::LogBuf() {
Init();
//std::cout << "LogBuf只初始化一次" << std::endl;
}
LogBuf::~LogBuf() {
UnInit();
//std::cout << "LogBuf只反向初始化一次" << std::endl;
}
bool LogBuf::Init(int len /* = 4096 */) {
m_buf = new char[len];
m_nowLen = 0;
m_maxLen = len;
return true;
}
bool LogBuf::UnInit() {
delete[] m_buf;
return true;
}
void LogBuf::Release() {
m_nowLen = 0;
}
uint32_t LogBuf::GetLen() {
return m_nowLen;
}
const char* LogBuf::GetBuf() {
return m_buf;
}
bool LogBuf::Append(const char* buf, uint32_t len) {
HandleExpandMemory(len);
memmove(m_buf + m_nowLen, buf, len);
m_nowLen += len;
return true;
}
char* LogBuf::GetCurAvailBuf() {
return m_buf + m_nowLen;
}
bool LogBuf::AddLen(uint32_t len) {
m_nowLen += len;
return true;
}
bool LogBuf::HandleExpandMemory(uint32_t len) {
if (_GetAvail() < len) {
m_maxLen *= 2;
char* buf = new char[m_maxLen];
memmove(buf, m_buf, m_nowLen);
delete[] m_buf;
m_buf = buf;
}
return true;
}
uint32_t LogBuf::_GetAvail() const {
return m_maxLen - m_nowLen;
}
LogBuf CLogger::ms_buf;
CLogger::~CLogger() {
ms_buf.Append("\0", 1);
assert(nullptr != gs_pLogger);
gs_pLogger->OutPut(gs_eLevel, &ms_buf);
}
bool CLogger::SetLogger(ILogger* pLogger) {
assert(nullptr != pLogger);
gs_pLogger = pLogger;
return true;
}
ILogger* CLogger::GetLogger() {
return gs_pLogger;
}
bool CLogger::SetLevel(LOG_LEVEL level) {
gs_eLevel = level;
return true;
}
LOG_LEVEL CLogger::GetLevel(){
return gs_eLevel;
}
CLogger& CLogger::operator<<(const char* pBuf) {
if (nullptr != pBuf) {
ms_buf.Append(pBuf, (uint32_t)strlen(pBuf));
}
else {
ms_buf.Append("(null)", 6);
}
return *this;
}
CLogger& CLogger::operator<<(int value) {
_FormateInterger(value);
return *this;
}
CLogger& CLogger::operator<<(uint64_t value) {
_FormateInterger(value);
return *this;
}
CLogger& CLogger::operator<<(const unsigned char* pBuf) {
return operator<<(reinterpret_cast<const char*>(pBuf));
}
CLogger& CLogger::operator<<(std::string& buf) {
ms_buf.Append(buf.c_str(), (uint32_t)buf.length());
return *this;
}
CLogger& CLogger::operator<<(const std::string& buf) {
ms_buf.Append(buf.c_str(), (uint32_t)buf.length());
return *this;
}
CLogger& CLogger::operator<<(unsigned int value) {
_FormateInterger(value);
return *this;
}
CLogger& CLogger::operator<<(bool b) {
if (b) {
ms_buf.Append("true", 4);
}
else {
ms_buf.Append("false", 5);
}
return *this;
}
CLogger& CLogger::operator<<(const void* p) {
uintptr_t value = reinterpret_cast<uintptr_t>(p);
ms_buf.HandleExpandMemory(sizeof(uintptr_t));
char* buf = ms_buf.GetCurAvailBuf();
buf[0] = '0';
buf[1] = 'x';
size_t len = _ConvertHex(buf + 2, value);
ms_buf.AddLen((uint32_t)len + 2);
return *this;
}
size_t CLogger::_ConvertHex(char* buf, uintptr_t value) {
static const char s_digitsHex[] = "0123456789ABCDEF";
uintptr_t i = value;
char* p = buf;
do {
int odd = static_cast<int>(i % 16);
i /= 16;
*p++ = s_digitsHex[odd];
} while (i != 0);
*p = '\0';
std::reverse(buf, p);
return p - buf;
}
}
#include "Logger.h"
class Log :public U::ILogger {
public:
//继承至 ILogger
virtual bool OutPut(U::LOG_LEVEL level, U::LogBuf* buf) override {
std::cout << buf->GetBuf() << std::endl;
buf->Release();
return true;
}
};
void LogPrint1() {
LOG_TRACE << "1111";
LOG_TRACE << "2222";
}
void LogPrint2() {
LOG_TRACE << "3333";
}
void LogPrint3() {
LOG_TRACE << "5555";
}
int main() {
Log log;
U::CLogger::SetLogger(&log);
U::CLogger::SetLevel(U::LOG_LEVEL::LOG_TRACE_LEVEL);
LogPrint1();
LogPrint2();
LogPrint3();
system("pause");
return 0;
}
运行结果:

构造和析构的调用本质:利用局部变量在作用于结束便后调用其析构函数的特性进行相应封装。
if(U::CLogger::GetLevel() <= U::LOG_LEVEL::LOG_DEBUG_LEVEL)
if(U::CLogger::GetLogger() != nullptr)
U::CLogger(__FUNCTION__, __LINE__, level) << "xxx";