首页 > 代码库 > 简单的日志系统

简单的日志系统

參考glog写了现有的Logging系统。

直接有

enum LoggingEnum{
LOG_INFO,
LOG_DBBUG,
LOG_ERROR,
LOG_WARNNING,
LOG_END
};

几种等级的日志,实时刷到console上,异步延迟写到日志上,建立队列缓存日志,时间一到一起刷到file,好了,看下Logging实现:

class Active;
struct Buffer;

enum LoggingEnum{
	LOG_INFO,
	LOG_DBBUG,
	LOG_ERROR,
	LOG_WARNNING,
	LOG_END
};

enum GLogColor {
	COLOR_DEFAULT,
	COLOR_RED,
	COLOR_GREEN,
	COLOR_YELLOW
};

class Logging
{
public:
	Logging();
	~Logging();
	void	WriteWithFunLine(LoggingEnum eLoggingEnum, char* fun, int line, char* msg, ...);	
	void	WriteBuffer(Buffer*& pBuffer);

private:
	INT32	CreateLogFile(LoggingEnum aLoggingEnum);
	void	Write(LoggingEnum eLoggingEnum, char* msg, int msgLen);

private:
	FILE*					m_File[LOG_END];
	Active*					m_pActive;
	typedef boost::posix_time::ptime PTIME;
	boost::atomic<BOOLEAN>	m_IfCanFlush[LOG_END];
	PTIME					m_PrelushTime[LOG_END];
	std::queue<Buffer*>		m_BufferQueue[LOG_END];
};

Logging g_Logging;
string LOGPreStr[LOG_END] = {"LOG_INFO", "LOG_DBBUG", "LOG_ERROR", "LOG_WARNNING"};

#ifdef _WINDOWS
// Returns the character attribute for the given color.
WORD GetColorAttribute(GLogColor color) {
	switch (color) {
	case COLOR_RED:    return FOREGROUND_RED;
	case COLOR_GREEN:  return FOREGROUND_GREEN;
	case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
	default:           return 0;
	}
}
#else
// Returns the ANSI color code for the given color.
const char* GetAnsiColorCode(GLogColor color) {
	switch (color) {
	case COLOR_RED:     return "1";
	case COLOR_GREEN:   return "2";
	case COLOR_YELLOW:  return "3";
	case COLOR_DEFAULT:  return "";
	};
	return NULL; // stop warning about return type.
}

#endif  // OS_WINDOWS

GLogColor GLogColorVec[LOG_END] = {COLOR_GREEN, COLOR_DEFAULT, COLOR_RED, COLOR_YELLOW};

Logging::Logging(){
	PTIME nowTime = boost::posix_time::microsec_clock::local_time();

	INT32 n32Res = eNormal;
	for (INT32 i = LOG_INFO; i < LOG_END; ++i){
		m_File[i] = NULL;
		m_IfCanFlush[i] = FALSE;
		m_PrelushTime[i] = nowTime;
		n32Res = CreateLogFile((LoggingEnum)i);
		if (n32Res != eNormal){
			printf("Createfile(i) failed", i);
		}
	}
	
	m_pActive = Active::CreateActive(std::bind(&Logging::WriteBuffer, this, std::placeholders::_1));
}

void Logging::Write(LoggingEnum eLoggingEnum, char* msg, int msgLen){
	Buffer* pBuffer = m_pActive->GetBuffer();
	pBuffer->m_LogLevel = eLoggingEnum;
	char* curData = http://www.mamicode.com/pBuffer->m_pMsg;>
当中用到的Active就是简单的生产者消费者模型:

struct  Buffer
{
	Buffer():m_LogLevel(0), m_Len(1024), m_pMsg(new char[m_Len]){}
	~Buffer(){
		if (NULL != m_pMsg)
			delete []m_pMsg;
	}
	Buffer(int size):m_LogLevel(0), m_Len(size)
		, m_pMsg(new char[m_Len]){

	}
	int		m_LogLevel;
	int		m_Len;
	char*	m_pMsg;
};

typedef std::function<void(Buffer*&)> Callback;

class Active {
private:
	Active(const Active&);
	Active& operator=(const Active&);
	Active(); 
	void doDone(){m_IfDone = true;}
	void Run();
	void setCallBack(Callback aCallBack);
	bool IfEmpty();
	int Consume(Buffer*& apBuffer);

	std::queue<Buffer*> m_Queue;
	boost::thread	m_Thread;
	volatile bool	m_IfDone;
	Callback		m_Callback;
	boost::mutex	m_Mutex;
	boost::mutex	m_ObjectMutex;
	CSSObejctPool<Buffer> m_pBufferPool;
	boost::condition_variable m_ConditionVar; 

public:
	~Active();
	Buffer*			GetBuffer();
	void			ReleaseBuffer(Buffer*& pBuffer);
	void			Send(Buffer* apBuffer);
	void			Stop();
	static Active*	CreateActive(Callback aCallBack);
};

Active::Active(): m_IfDone(false){}

Active::~Active() {
	Stop();
}

void Active::Send( Buffer* apBuffer ){
	if (NULL != apBuffer){
		boost::mutex::scoped_lock lock(m_Mutex);
		bool bNeedSig = m_Queue.empty();
		m_Queue.push(apBuffer);
		if (bNeedSig){
			m_ConditionVar.notify_one();
		}
	}
}

void Active::Run() {
	Buffer* pBuffer = NULL;
	while (!m_IfDone && 0 == Consume(pBuffer)){
		m_Callback(pBuffer);
		if (NULL != pBuffer){
			boost::mutex::scoped_lock lock(m_ObjectMutex);
			m_pBufferPool.ReleaseObejct(pBuffer);
		}
	}
}

Active* Active::CreateActive(Callback aCallBack){
	Active* aPtr = new Active();
	aPtr->m_Thread = boost::thread(&Active::Run, aPtr);
	aPtr->m_Callback = aCallBack;
	return aPtr;
}

void Active::setCallBack(Callback aCallBack){
	m_Callback = aCallBack;
}

Buffer* Active::GetBuffer(){
	boost::mutex::scoped_lock lock(m_ObjectMutex);
	return m_pBufferPool.AcquireObject();
}

bool Active::IfEmpty(){
	return m_Queue.empty();  
}

int Active::Consume(Buffer*& apBuffer){
	boost::mutex::scoped_lock lock(m_Mutex);
	while (m_Queue.empty()){
		if (m_IfDone){
			return 1;
		}
		m_ConditionVar.wait(lock);
	}

	if (m_IfDone){
		return 1;
	}

	apBuffer = m_Queue.front();
	m_Queue.pop();

	return 0;
}

void Active::Stop(){
	m_IfDone = true;
	m_ConditionVar.notify_one();
}

void Active::ReleaseBuffer(Buffer*& pBuffer){
	if (NULL != pBuffer){
		boost::mutex::scoped_lock lock(m_ObjectMutex);
		m_pBufferPool.ReleaseObejct(pBuffer);
		pBuffer = NULL;
	}
}

ok!仅仅有4个文件,仅仅要有boost库就能够编译使用了。用到的objectpool是之前博客介绍过的内存池。