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

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


#include "Generic.h"
enum LOG_TYPE
{
    LOG_DEAGNOSTIC_MSG  = 0x00000000,
    LOG_EVENT           = 0x00000001,
    LOG_ACTIVITY        = 0x00000002,
    LOG_ERROR           = 0x00000004,
};


class CAppLog {
public:
    CAppLog();
    virtual ~CAppLog();


    static void appendDeagnosticMsg( const char * lpszFmt, ...);
    static void appendEvent( const char * lpszFmt, ...);
    static void appendActivity( const char * lpszFmt, ...);
    static void appendError( const char * lpszFmt, ...);




private:
    static sem_t *      s_pLogFileSem;


    static void append(LOG_TYPE emType, const char * lpszText);
};




#endif /* CAPPLOG_H_ */


以下是它的实现

/*
 * CAppLog.cpp
 *
 *  Created on: Jan 1, 2009
 *      Author: root
 */


#include "CAppLog.h"
#include "CSystemHelper.h"


#define LOG_SEM_NAME    "LogFileSem"




sem_t * CAppLog::s_pLogFileSem = NULL;
CAppLog g_oAppLog;




CAppLog::CAppLog() {
    if( s_pLogFileSem == NULL )
    {
        s_pLogFileSem = sem_open( LOG_SEM_NAME, O_CREAT, 0666, 1);
    }
}


CAppLog::~CAppLog() {
    if( s_pLogFileSem != NULL )
    {
        sem_close(s_pLogFileSem);
        s_pLogFileSem = NULL;
    }
}


void CAppLog::append(LOG_TYPE emType, const char * lpszText)
{
    char szBuffer[10240] = {0};
    int nRet = readlink("/proc/self/exe", szBuffer, sizeof(szBuffer));
    if( nRet <= 0 || nRet >= PATH_MAX )
        return;


    string strTemp(szBuffer);
    string strDir = strTemp.substr(0, strTemp.rfind( '/') + 1);
    string strExe = strTemp.substr(strTemp.rfind( '/') + 1);


    time_t ulNow = {0};
    time(&ulNow);
    tm * pNow = localtime(&ulNow);
    memset( szBuffer, 0, sizeof(szBuffer));
    sprintf( szBuffer, "%sLog/%04d/%04d-%02d/"
            , strDir.c_str()
            , 1900 + pNow->tm_year
            , 1900 + pNow->tm_year
            , 1 + pNow->tm_mon
            );
    CSystemHelper::createDirectory(szBuffer);
    sprintf( szBuffer, "%sLog/%04d/%04d-%02d/%04d-%02d-%02d.log"
            , strDir.c_str()
            , 1900 + pNow->tm_year
            , 1900 + pNow->tm_year
            , 1 + pNow->tm_mon
            , 1900 + pNow->tm_year
            , 1 + pNow->tm_mon
            , pNow->tm_mday
            );


    sem_wait(s_pLogFileSem);


    {
        ofstream stream( szBuffer,ios::out | ios::app);
        if( stream )
        {
            char szFormated[20480] = {0};
            sprintf( szFormated, "\r\n%02d[%02d:%02d:%02d PID=%05d TID=%05ld EXE=%-15s] %s"
                    , emType
                    , pNow->tm_hour
                    , pNow->tm_min
                    , pNow->tm_sec
                    , getpid()
                    , (long)syscall(SYS_gettid)
                    , strExe.c_str()
                    , lpszText
                    );
            stream << szFormated;
            stream.flush();
            stream.close();
        }
    }


    sem_post(s_pLogFileSem);
}


void CAppLog::appendDeagnosticMsg( const char * lpszFmt, ...)
{
    va_list arg;
    va_start(arg, lpszFmt);
    char szBuffer[10240] = {0};
    vsprintf( szBuffer, lpszFmt, arg);
    va_end(arg);


    CAppLog::append( LOG_DEAGNOSTIC_MSG, szBuffer);
}


void CAppLog::appendEvent( const char * lpszFmt, ...)
{
    va_list arg;
    va_start(arg, lpszFmt);
    char szBuffer[10240] = {0};
    vsprintf( szBuffer, lpszFmt, arg);
    va_end(arg);


    CAppLog::append( LOG_EVENT, szBuffer);
}


void CAppLog::appendActivity( const char * lpszFmt, ...)
{
    va_list arg;
    va_start(arg, lpszFmt);
    char szBuffer[10240] = {0};
    vsprintf( szBuffer, lpszFmt, arg);
    va_end(arg);


    CAppLog::append( LOG_ACTIVITY, szBuffer);
}


void CAppLog::appendError( const char * lpszFmt, ...)
{
    va_list arg;
    va_start(arg, lpszFmt);
    char szBuffer[10240] = {0};
    vsprintf( szBuffer, lpszFmt, arg);
    va_end(arg);


    CAppLog::append( LOG_ERROR, szBuffer);
}



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


void CSystemHelper::createDirectory(const char * lpszDir)
{
    string strDir(lpszDir);
    int nIndex = 0;
    while(nIndex != string::npos)
    {
        int nFind = strDir.find( "/", nIndex+1);
        string strTemp = strDir.substr( 0, nFind+1);
        DIR *dir = opendir(strTemp.c_str());
        if( dir != NULL )
            closedir(dir);
        else
            mkdir( strTemp.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);

        nIndex = nFind;
    }
}
posted on 2010-06-01 09:30  carekee  阅读(631)  评论(0编辑  收藏  举报