一个进程安全的日志类, 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;
}
}