日志类简单封装

#ifndef __LOGMANAGER__H_
#define __LOGMANAGER__H_
#include <cstdio>
#include <queue>
#include <string>
#include "singleton.h"
#include "util.h"
#include "CMutex.h"
#include "CThread.h"
using namespace std;
enum LogType{ LOG_TYPE_SCREEN = 0, LOG_TYPE_FILE, LOG_TYPE_MAX};
enum LogLevel{
	LOG_LEVEL_ERR = 0,
	LOG_LEVEL_DBG,
	LOG_LEVEL_INFO,
	LOG_LEVEL_FUNCTION,

	LOG_LEVEL_MAX
};

#define MAX_PER_LOGFILE_SIZE 500*1024*1024	//单个日志文件的大小为500M
#define MAX_PER_LINE_LOG	2048	//一行日志最大缓存

struct tagLogItem
{
	int iLevel;
	string strLog;
};

class CLogmanger : public CSingleton<CLogmanger>, CThread
{
	SINGLE_CLASS_INITIAL(CLogmanger);

public:
	int Init(int iType, int iLevel, const char* szDir);
	~CLogmanger();
	void AddLogItem(int iLevel, const char *format, ...);
	int StopLog();
	int SetLogType(int iType);

protected:
	 virtual void* work();

private:
	int Check();
	FILE* GetFile();

private:
	int m_iType;
	int m_iLevel;
	unsigned long m_lCount;
	bool m_bInit;
	string m_strDir;
	FILE* m_pFile;
	queue<tagLogItem> m_qLogItems;
};

#define sLog CLogmanger::Instance()

#define LOG_ERR(fmt, ...) sLog->AddLogItem(LOG_LEVEL_ERR, "[ERROR](%s:%s:%d)[Thread:%ld] " fmt, __FILE__, __FUNCTION__, __LINE__, get_thread_id_self(), ##__VA_ARGS__)
#define LOG_DBG(fmt, ...) sLog->AddLogItem(LOG_LEVEL_DBG, "[DEBUG](%s:%s:%d)[Thread:%ld] " fmt, __FILE__, __FUNCTION__, __LINE__, get_thread_id_self(), ##__VA_ARGS__)
#define LOG_INFO(fmt, ...) sLog->AddLogItem(LOG_LEVEL_INFO, "[INFO][Thread:%ld] " fmt, get_thread_id_self(), ##__VA_ARGS__)
#define LOG_FUNCTION(fmt, ...) sLog->AddLogItem(LOG_LEVEL_DBG, "[FUNCTION](%s)[Thread:%ld] " fmt, __FUNCTION__, get_thread_id_self(), ##__VA_ARGS__)

#define ASSERT(expr) do{if (!(expr)){LOG_ERR("assert \"%s\" failed", #expr);}}while(0)
#define ASSERT_RET(expr) do{if (!(expr)){LOG_ERR("assert \"%s\" failed", #expr); return ; }}while(0)
#define ASSERT_RET_VALUE(expr, retval) do{if (!(expr)){LOG_ERR("assert \"%s\" failed", #expr); return retval; }}while(0)

#define ASSERT_ERR_MSG(expr, fmt, ...) \
do \
{ \
if (!(expr)) \
{ \
	LOG_ERR("assert \"%s\", msg:" fmt, #expr, ##__VA_ARGS__); \
} \
} while (0);

#define ASSERT_ERR_MSG_RET(expr, retval, fmt, ...) \
do \
{ \
if (!(expr)) \
{ \
	LOG_ERR("assert \"%s\", msg:" fmt, #expr, ##__VA_ARGS__); \
	return retval; \
} \
} while (0);

#endif

#include "stdafx.h"
#include "CLogmanager.h"

#define RESET           0  
#define BRIGHT          1  
#define DIM             2  
#define UNDERLINE       4  
#define BLINK           5  
#define REVERSE         7  
#define HIDDEN          8  

#define BLACK           0  
#define RED             1  
#define GREEN           2  
#define YELLOW          3  
#define BLUE            4  
#define MAGENTA         5  
#define CYAN            6  
#define WHITE           7 

#if defined(WIN32) || defined(_WIN32)
#elif  __linux__
#define COLOR_PRINT_BEGIN	\033
#define COLOR_PRINT_END	\033[0m
#endif

CLogmanger::CLogmanger()
{
	m_iLevel = LOG_LEVEL_ERR;
	m_iType = LOG_TYPE_SCREEN;
	m_lCount = 0;
	m_pFile = NULL;
	m_strDir = "";
	m_bInit = false;
}

CLogmanger::~CLogmanger()
{
	if (NULL != m_pFile)
	{
		fclose(m_pFile);
		m_pFile = NULL;
	}
}

FILE* CLogmanger::GetFile()
{
	if (m_iType == LOG_TYPE_FILE)
	{
		if (NULL != m_pFile && m_pFile != stdout)
		{
			fclose(m_pFile);
			m_pFile = NULL;
		}

		struct system_time_t stNow = get_now_time();
		char szFileName[1000];
		safe_snprintf(szFileName, 1000, _TRUNCATE, "%02d-%02d-%02d-%02d-%02d-%02d.log", stNow.tm_year, stNow.tm_mon, stNow.tm_mday,
			stNow.tm_hour, stNow.tm_min, stNow.tm_sec);

		string strTmp = m_strDir;
		if (!str_end_with(strTmp, "\\") && !str_end_with(strTmp, "/"))
		{
			strTmp += "/";
		}

		strTmp += szFileName;
		m_pFile = safe_open_file(strTmp.c_str(), "a+");
		if (nullptr == m_pFile)
		{
			m_pFile = stdout;
		}
	}
	else
	{
		if (NULL != m_pFile && m_pFile != stdout)
		{
			fclose(m_pFile);
		}

		m_pFile = stdout;
	}
	
	return m_pFile;
}

int CLogmanger::Check()
{
	//文件过大创建新文件
	if (m_iType == LOG_TYPE_FILE && m_lCount >= MAX_PER_LOGFILE_SIZE)
	{
		GetFile();
		if (m_pFile != nullptr)
		{
			m_lCount = 0;
		}
	}

	return 0;
}

int CLogmanger::SetLogType(int iType)
{
	if (!m_bInit || iType < LOG_TYPE_SCREEN || iType >= LOG_TYPE_MAX)
	{
		return -1;
	}

	if (iType == m_iType)
	{
		return 0;
	}

	m_iType = iType;
	GetFile();

	return 0;
}

void CLogmanger::AddLogItem(int iLevel, const char *format, ...)
{
	if (iLevel > m_iLevel || iLevel > LOG_LEVEL_MAX || !m_bInit)
	{
		return;
	}

	char szBuf[MAX_PER_LINE_LOG];
	memset(szBuf, 0, sizeof(szBuf));
	int nPos = 0;
	struct system_time_t stNow = get_now_time();
	nPos = safe_snprintf(szBuf, MAX_PER_LINE_LOG - 1, _TRUNCATE, "[%02d/%02d/%02d %02d:%02d:%02d.%06d] ", stNow.tm_year, stNow.tm_mon, stNow.tm_mday, stNow.tm_hour, stNow.tm_min, stNow.tm_sec, stNow.tm_milliseconds);
	
	va_list ap;
	va_start(ap, format);
#if defined(WIN32) || defined(_WIN32)
	nPos += vsnprintf_s(szBuf + nPos, MAX_PER_LINE_LOG - nPos - 1, _TRUNCATE, format, ap);
#elif  __linux__
	nPos += vsnprintf(szBuf + nPos, MAX_PER_LINE_LOG - nPos - 1, format, ap);
#endif
	va_end(ap);

	if (nPos > MAX_PER_LINE_LOG - 1)
	{
		nPos = MAX_PER_LINE_LOG - 1;
	}
		
	if (nPos > 0)
	{
		szBuf[nPos] = '\0';
	}

	tagLogItem stLog;
	stLog.iLevel = iLevel;
	stLog.strLog = szBuf;
	m_cMutex.Lock();
	m_qLogItems.push(stLog);
	m_cMutex.UnLock();
}

int CLogmanger::Init(int iType, int iLevel, const char* szDir)
{
	if (m_bInit)
	{
		return 1;
	}

	m_iType = iType;
	m_iLevel = iLevel;
	if (nullptr != szDir && strlen(szDir) > 0)
	{
		m_strDir = szDir;
	}
	else
	{
		m_strDir = get_app_path();
	}

	if (iType == LOG_TYPE_FILE)
	{
		if (make_dirs(szDir))
		{
			return 1;
		}
	}
	
	GetFile();

	if (NULL == m_pFile)
	{
		return 1;
	}
	else
	{
		Start();
	}

	m_bInit = true;
	return 0;
}

int CLogmanger::StopLog()
{
	m_bInit = false;
	return Stop();
}

void* CLogmanger::work()
{
	while (!m_bStop)
	{
		bool bBusy = false;
		m_cMutex.Lock();
		if (!m_qLogItems.empty())
		{
			tagLogItem stLog = m_qLogItems.front();
#if defined(WIN32) || defined(_WIN32)
				if (m_iType == LOG_TYPE_SCREEN && stLog.iLevel == LOG_LEVEL_ERR)
				{
					SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
				}
#endif
			
			fprintf(m_pFile, "%s\n", stLog.strLog.c_str());

#if defined(WIN32) || defined(_WIN32)
			if (m_iType == LOG_TYPE_SCREEN && stLog.iLevel == LOG_LEVEL_ERR)
			{
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);
			}
#endif
			m_qLogItems.pop();
			bBusy = true;
			m_lCount += (unsigned long)stLog.strLog.size();
		}
		m_cMutex.UnLock();

		Check();
		fflush(m_pFile);
		if (!bBusy)
		{
			Wait();
		}
	}
	return nullptr;
}

猜你喜欢

转载自blog.csdn.net/lightjia/article/details/79897163