Simple Log System

Source: Internet
Author: User

Refer to glog to write the existing logging system.

Directly available

Enum loggingenum {
Log_info,
Log_dbbug,
Log_error,
Log_warnning,
Log_end
};

Logs of several levels are flushed to the console in real time, asynchronously written to logs with latency, and queue cache logs are established. The time is flushed together to file. Well, let's take a look at the implementation of 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();voidWriteWithFunLine(LoggingEnum eLoggingEnum, char* fun, int line, char* msg, ...);voidWriteBuffer(Buffer*& pBuffer);private:INT32CreateLogFile(LoggingEnum aLoggingEnum);voidWrite(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];PTIMEm_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_WINDOWSGLogColor 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 = pBuffer->m_pMsg;pBuffer->m_Len = msgLen;memcpy(curData, msg, msgLen);m_pActive->Send(pBuffer);}void Logging::WriteBuffer(Buffer*& pBuffer){char* pContent = pBuffer->m_pMsg;pContent[pBuffer->m_Len] = '\0';const GLogColor color = GLogColorVec[pBuffer->m_LogLevel];#ifdef _WINDOWSconst HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);CONSOLE_SCREEN_BUFFER_INFO buffer_info;GetConsoleScreenBufferInfo(stderr_handle, &buffer_info);const WORD old_color_attrs = buffer_info.wAttributes;fflush(stderr);SetConsoleTextAttribute(stderr_handle,GetColorAttribute(color) | FOREGROUND_INTENSITY);fwrite(pContent, pBuffer->m_Len+1, 1, stderr);fflush(stderr);SetConsoleTextAttribute(stderr_handle, old_color_attrs);#elsefprintf(stderr, "\033[0;3%sm", GetAnsiColorCode(color));fwrite(message, len, 1, stderr);fprintf(stderr, "\033[m");  // Resets the terminal to default.#endifFILE* pNowFile = m_File[pBuffer->m_LogLevel];if (pNowFile == NULL){return;}std::queue<Buffer*>& bufferQueue = m_BufferQueue[pBuffer->m_LogLevel];if (FALSE == m_IfCanFlush[pBuffer->m_LogLevel]){bufferQueue.push(pBuffer);pBuffer = NULL;}else{while (FALSE == bufferQueue.empty()){Buffer* pPreBuffer = bufferQueue.front();bufferQueue.pop();fwrite(pPreBuffer->m_pMsg, 1, pPreBuffer->m_Len, pNowFile);fflush(pNowFile);m_pActive->ReleaseBuffer(pPreBuffer);}fwrite(pContent, 1, pBuffer->m_Len, pNowFile);fflush(pNowFile);m_IfCanFlush[pBuffer->m_LogLevel] = FALSE;m_PrelushTime[pBuffer->m_LogLevel] = boost::posix_time::microsec_clock::local_time();} }void Logging::WriteWithFunLine(LoggingEnum eLoggingEnum, char* fun, int line, char* msg, ...){if (eLoggingEnum < LOG_INFO || eLoggingEnum > LOG_WARNNING){eLoggingEnum = eLoggingEnum;}char tmp[1024] = {0};PTIME nowTime = boost::posix_time::microsec_clock::local_time();boost::posix_time::time_duration timeFidd = nowTime - m_PrelushTime[eLoggingEnum];if (timeFidd.total_microseconds() > 1000){m_IfCanFlush[eLoggingEnum] = TRUE;}sprintf(tmp, "%s.%d %s:%d ", boost::posix_time::to_iso_string(nowTime).c_str(), boost::this_thread::get_id(), fun, line);int curPos = strlen(tmp);va_list pArg = NULL;va_start(pArg, msg);vsprintf(tmp+curPos, msg, pArg);va_end(pArg);curPos = strlen(tmp);char end[] = "\n";sprintf(tmp + curPos, "%s", end);Write(eLoggingEnum, tmp, strlen(tmp));}Logging::~Logging(){for (INT32 i = 0; i < 4; ++i){if (NULL != m_File[i]){fclose(m_File[i]);}}delete m_pActive;}INT32 Logging::CreateLogFile(LoggingEnum aLoggingEnum){string strPre;switch (aLoggingEnum){case LOG_DBBUG:strPre = "LOG_DBBUG";break;case LOG_INFO:strPre = "LOG_INFO";break;case LOG_WARNNING:strPre = "LOG_WARNNING";break;case LOG_ERROR:strPre = "LOG_ERROR";break;}char str[128];sprintf(str, "./Log/%s-%d-%s", strPre.c_str() ,boost::this_thread::get_id(), boost::posix_time::to_iso_string(boost::posix_time::microsec_clock::local_time()).c_str());string fileName(str);fileName += ".log";int fd = open(fileName.c_str(), O_WRONLY | O_CREAT | O_EXCL, 0664);if (fd == -1){printf("%s create(%d) file error\n", __FUNCTION__, aLoggingEnum);return -1;}m_File[aLoggingEnum] = fdopen(fd, "a");if (NULL == m_File[aLoggingEnum]){printf("%s open file(%d) failed\n", __FUNCTION__, aLoggingEnum);return -1;}return 0;}

The active mode is a simple producer and consumer model:

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]){}intm_LogLevel;intm_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::threadm_Thread;volatile boolm_IfDone;Callbackm_Callback;boost::mutexm_Mutex;boost::mutexm_ObjectMutex;CSSObejctPool<Buffer> m_pBufferPool;boost::condition_variable m_ConditionVar; public:~Active();Buffer*GetBuffer();voidReleaseBuffer(Buffer*& pBuffer);voidSend(Buffer* apBuffer);voidStop();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! There are only four files, which can be compiled and used as long as there is a boost library. The objectpool used is the memory pool introduced by the blog.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.