一个进程安全的日志类, Linux实现

本文介绍了一个用于多进程环境中分类记录日志的C++类CAppLog。该类能够根据不同的日志类型(诊断消息、事件、活动、错误)记录日志,并通过信号量同步确保日志写入的线程安全。

项目中需要分类日志功能,且日志由多个进程产生,所以写了这个类。

  1. #ifndef CAPPLOG_H_
  2. #define CAPPLOG_H_
  3. #include "Generic.h"
  4. enum LOG_TYPE
  5. {
  6.     LOG_DEAGNOSTIC_MSG  = 0x00000000,
  7.     LOG_EVENT           = 0x00000001,
  8.     LOG_ACTIVITY        = 0x00000002,
  9.     LOG_ERROR           = 0x00000004,
  10. };
  11. class CAppLog {
  12. public:
  13.     CAppLog();
  14.     virtual ~CAppLog();
  15.     static void appendDeagnosticMsg( const char * lpszFmt, ...);
  16.     static void appendEvent( const char * lpszFmt, ...);
  17.     static void appendActivity( const char * lpszFmt, ...);
  18.     static void appendError( const char * lpszFmt, ...);
  19. private:
  20.     static sem_t *      s_pLogFileSem;
  21.     static void append(LOG_TYPE emType, const char * lpszText);
  22. };
  23. #endif /* CAPPLOG_H_ */

以下是它的实现

  1. /*
  2.  * CAppLog.cpp
  3.  *
  4.  *  Created on: Jan 1, 2009
  5.  *      Author: root
  6.  */
  7. #include "CAppLog.h"
  8. #include "CSystemHelper.h"
  9. #define LOG_SEM_NAME    "LogFileSem"
  10. sem_t * CAppLog::s_pLogFileSem = NULL;
  11. CAppLog g_oAppLog;
  12. CAppLog::CAppLog() {
  13.     if( s_pLogFileSem == NULL )
  14.     {
  15.         s_pLogFileSem = sem_open( LOG_SEM_NAME, O_CREAT, 0666, 1);
  16.     }
  17. }
  18. CAppLog::~CAppLog() {
  19.     if( s_pLogFileSem != NULL )
  20.     {
  21.         sem_close(s_pLogFileSem);
  22.         s_pLogFileSem = NULL;
  23.     }
  24. }
  25. void CAppLog::append(LOG_TYPE emType, const char * lpszText)
  26. {
  27.     char szBuffer[10240] = {0};
  28.     int nRet = readlink("/proc/self/exe", szBuffer, sizeof(szBuffer));
  29.     if( nRet <= 0 || nRet >= PATH_MAX )
  30.         return;
  31.     string strTemp(szBuffer);
  32.     string strDir = strTemp.substr(0, strTemp.rfind( '/') + 1);
  33.     string strExe = strTemp.substr(strTemp.rfind( '/') + 1);
  34.     time_t ulNow = {0};
  35.     time(&ulNow);
  36.     tm * pNow = localtime(&ulNow);
  37.     memset( szBuffer, 0, sizeof(szBuffer));
  38.     sprintf( szBuffer, "%sLog/%04d/%04d-%02d/"
  39.             , strDir.c_str()
  40.             , 1900 + pNow->tm_year
  41.             , 1900 + pNow->tm_year
  42.             , 1 + pNow->tm_mon
  43.             );
  44.     CSystemHelper::createDirectory(szBuffer);
  45.     sprintf( szBuffer, "%sLog/%04d/%04d-%02d/%04d-%02d-%02d.log"
  46.             , strDir.c_str()
  47.             , 1900 + pNow->tm_year
  48.             , 1900 + pNow->tm_year
  49.             , 1 + pNow->tm_mon
  50.             , 1900 + pNow->tm_year
  51.             , 1 + pNow->tm_mon
  52.             , pNow->tm_mday
  53.             );
  54.     sem_wait(s_pLogFileSem);
  55.     {
  56.         ofstream stream( szBuffer,ios::out | ios::app);
  57.         if( stream )
  58.         {
  59.             char szFormated[20480] = {0};
  60.             sprintf( szFormated, "/r/n%02d[%02d:%02d:%02d PID=%05d TID=%05ld EXE=%-15s] %s"
  61.                     , emType
  62.                     , pNow->tm_hour
  63.                     , pNow->tm_min
  64.                     , pNow->tm_sec
  65.                     , getpid()
  66.                     , (long)syscall(SYS_gettid)
  67.                     , strExe.c_str()
  68.                     , lpszText
  69.                     );
  70.             stream << szFormated;
  71.             stream.flush();
  72.             stream.close();
  73.         }
  74.     }
  75.     sem_post(s_pLogFileSem);
  76. }
  77. void CAppLog::appendDeagnosticMsg( const char * lpszFmt, ...)
  78. {
  79.     va_list arg;
  80.     va_start(arg, lpszFmt);
  81.     char szBuffer[10240] = {0};
  82.     vsprintf( szBuffer, lpszFmt, arg);
  83.     va_end(arg);
  84.     CAppLog::append( LOG_DEAGNOSTIC_MSG, szBuffer);
  85. }
  86. void CAppLog::appendEvent( const char * lpszFmt, ...)
  87. {
  88.     va_list arg;
  89.     va_start(arg, lpszFmt);
  90.     char szBuffer[10240] = {0};
  91.     vsprintf( szBuffer, lpszFmt, arg);
  92.     va_end(arg);
  93.     CAppLog::append( LOG_EVENT, szBuffer);
  94. }
  95. void CAppLog::appendActivity( const char * lpszFmt, ...)
  96. {
  97.     va_list arg;
  98.     va_start(arg, lpszFmt);
  99.     char szBuffer[10240] = {0};
  100.     vsprintf( szBuffer, lpszFmt, arg);
  101.     va_end(arg);
  102.     CAppLog::append( LOG_ACTIVITY, szBuffer);
  103. }
  104. void CAppLog::appendError( const char * lpszFmt, ...)
  105. {
  106.     va_list arg;
  107.     va_start(arg, lpszFmt);
  108.     char szBuffer[10240] = {0};
  109.     vsprintf( szBuffer, lpszFmt, arg);
  110.     va_end(arg);
  111.     CAppLog::append( LOG_ERROR, szBuffer);
  112. }


使用起来很简单,将类加入到工程,然后在需要的地方包含此类的头文件,然后直接调用静态方法。这里用到了一个辅助类的函数 CSystemHelper::createDirectory,它的实现如下:

  1. void CSystemHelper::createDirectory(const char * lpszDir)
  2. {
  3.     string strDir(lpszDir);
  4.     int nIndex = 0;
  5.     while(nIndex != string::npos)
  6.     {
  7.         int nFind = strDir.find( "/", nIndex+1);
  8.         string strTemp = strDir.substr( 0, nFind+1);
  9.         DIR *dir = opendir(strTemp.c_str());
  10.         if( dir != NULL )
  11.             closedir(dir);
  12.         else
  13.             mkdir( strTemp.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
  14.         nIndex = nFind;
  15.     }
  16. }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值