服務器公共庫開發--log系統
實現了簡易的log打印,有以下的特點:
1) 支持向標準輸出或者文件打印log
2) 向文件打印log時限制log文件的大小, 同時, 如果在文件大小超出范圍的時候, 可以選擇下一個文件進行打印.在這里, 文件大小和文件的數量都是可以配置的.
3) 支持分級別打印, 目前分的級別有DEBUG,ERROR,WARN,INFO這幾種, 在打印時, 也可以通過宏來開啟DEBUG,WARN的log.
4) 在向文件打印log時, 支持多線程, 同樣的, 這個也是可以配置的.
分為三個文件,log.h是對外的接口, 提供對文件打印log和對標準輸出打印log的簡易封裝, 具體使用哪種方式, 可以通過宏進行配置;logger.h和logger.cpp是對文件進行打印的類封裝, 是一個單件類, 因此繼承自前面提過的singleton類.
log.h:
logger.h
logger.cpp
1) 支持向標準輸出或者文件打印log
2) 向文件打印log時限制log文件的大小, 同時, 如果在文件大小超出范圍的時候, 可以選擇下一個文件進行打印.在這里, 文件大小和文件的數量都是可以配置的.
3) 支持分級別打印, 目前分的級別有DEBUG,ERROR,WARN,INFO這幾種, 在打印時, 也可以通過宏來開啟DEBUG,WARN的log.
4) 在向文件打印log時, 支持多線程, 同樣的, 這個也是可以配置的.
分為三個文件,log.h是對外的接口, 提供對文件打印log和對標準輸出打印log的簡易封裝, 具體使用哪種方式, 可以通過宏進行配置;logger.h和logger.cpp是對文件進行打印的類封裝, 是一個單件類, 因此繼承自前面提過的singleton類.
log.h:
/********************************************************************
created: 2008/08/02
filename: log.h
author: Lichuang
purpose: log模塊的對外接口, 可以根據宏將log打印到文件或者標準
輸出
*********************************************************************/
#ifndef __LOG_H__
#define __LOG_H__
#ifdef __USE_LOG_FILE__
#include "logger.h"
#define LOG(runlevel, file, lineno, args) \
do \
{ \
CLogger::GetInstance()->Log( \
runlevel, file, \
lineno, args); \
} while (0)
#define RUN_MSG_LOG(
) LOG(INFO, __FILE__, __LINE__, __VA_ARGS__);
#define ERROR_MSG_LOG(
) LOG(ERROR, __FILE__, __LINE__, __VA_ARGS__);
#ifdef LOG_DEBUG_MSG
#define DEBUG_MSG_LOG(
) LOG(DEBUG, __FILE__, __LINE__, __VA_ARGS__);
#else
#define DEBUG_MSG_LOG(
)
#endif
#ifdef LOG_WARN_MSG
#define WARN_MSG_LOG(
) LOG(WARN, __FILE__, __LINE__, __VA_ARGS__);
#else
#define WARN_MSG_LOG(
)
#endif
#else
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdarg.h>
#include <sys/time.h>
#define LOG(runlevel, file, lineno, args) \
do{ \
struct timeval now;\
gettimeofday(&now,0); \
struct tm *ptm=localtime(&(now.tv_sec)); \
fprintf(runlevel, "[%d:%d] [%s:%d]",ptm->tm_hour,ptm->tm_min, file,lineno); \
fprintf(runlevel, args); \
fprintf(runlevel, "\n"); \
}while(0)
#define RUN_MSG_LOG(
) LOG(stdout, __FILE__, __LINE__, __VA_ARGS__);
#define ERROR_MSG_LOG(
) LOG(stderr, __FILE__, __LINE__, __VA_ARGS__);
#ifdef LOG_DEBUG_MSG
#define DEBUG_MSG_LOG(
) LOG(stdout, __FILE__, __LINE__, __VA_ARGS__);
#else
#define DEBUG_MSG_LOG(
)
#endif
#ifdef LOG_WARN_MSG
#define WARN_MSG_LOG(
) LOG(stdout, __FILE__, __LINE__, __VA_ARGS__);
#else
#define WARN_MSG_LOG(
)
#endif
#endif
#endif /* __LOG_H__ */
created: 2008/08/02
filename: log.h
author: Lichuang
purpose: log模塊的對外接口, 可以根據宏將log打印到文件或者標準
輸出
*********************************************************************/
#ifndef __LOG_H__
#define __LOG_H__
#ifdef __USE_LOG_FILE__
#include "logger.h"
#define LOG(runlevel, file, lineno, args) \
do \
{ \
CLogger::GetInstance()->Log( \
runlevel, file, \
lineno, args); \
} while (0)
#define RUN_MSG_LOG(
) LOG(INFO, __FILE__, __LINE__, __VA_ARGS__);#define ERROR_MSG_LOG(
) LOG(ERROR, __FILE__, __LINE__, __VA_ARGS__);#ifdef LOG_DEBUG_MSG
#define DEBUG_MSG_LOG(
) LOG(DEBUG, __FILE__, __LINE__, __VA_ARGS__);#else
#define DEBUG_MSG_LOG(
) #endif
#ifdef LOG_WARN_MSG
#define WARN_MSG_LOG(
) LOG(WARN, __FILE__, __LINE__, __VA_ARGS__);#else
#define WARN_MSG_LOG(
) #endif
#else
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdarg.h>
#include <sys/time.h>
#define LOG(runlevel, file, lineno, args) \
do{ \
struct timeval now;\
gettimeofday(&now,0); \
struct tm *ptm=localtime(&(now.tv_sec)); \
fprintf(runlevel, "[%d:%d] [%s:%d]",ptm->tm_hour,ptm->tm_min, file,lineno); \
fprintf(runlevel, args); \
fprintf(runlevel, "\n"); \
}while(0)
#define RUN_MSG_LOG(
) LOG(stdout, __FILE__, __LINE__, __VA_ARGS__);#define ERROR_MSG_LOG(
) LOG(stderr, __FILE__, __LINE__, __VA_ARGS__);#ifdef LOG_DEBUG_MSG
#define DEBUG_MSG_LOG(
) LOG(stdout, __FILE__, __LINE__, __VA_ARGS__);#else
#define DEBUG_MSG_LOG(
) #endif
#ifdef LOG_WARN_MSG
#define WARN_MSG_LOG(
) LOG(stdout, __FILE__, __LINE__, __VA_ARGS__);#else
#define WARN_MSG_LOG(
) #endif
#endif
#endif /* __LOG_H__ */
logger.h
/********************************************************************
created: 2008/08/02
filename: logger.h
author: Lichuang
purpose: 實現簡易的log打印
*********************************************************************/
#ifndef __LOGGER_H__
#define __LOGGER_H__
#include "defines.h"
#include "singleton.h"
#include "threadmutex.h"
#include <string>
using namespace std;
struct LogInfo
{
int nFileNum;
string strFileSuffix;
string strFileName;
};
enum
{
DEBUG = 0,
WARN,
ERROR,
INFO,
NUM_OF_LOG_LEVEL
};
class CLogger
: public CSingleton<CLogger>
{
public:
public:
int Init(const string& strLogPath, const string& strFileName);
int Log(int nLogLevel, const char* pFileName, int nLine, const char *szFormat,
);
private:
DECLARE_SINGLETON_CLASS(CLogger)
CLogger();
virtual ~CLogger();
int GetFileName(int nLogLevel);
int CheckFileSize(const string& strFileName);
void GenerateFileName(string& strFileName, int nFileNum, int nLogLevel);
private:
string m_strLogPath;
string m_strFileName;
LogInfo m_szLogInfo[NUM_OF_LOG_LEVEL];
CThreadMutex m_tThreadMutex;
};
#endif /* __LOGGER_H__ */
created: 2008/08/02
filename: logger.h
author: Lichuang
purpose: 實現簡易的log打印
*********************************************************************/
#ifndef __LOGGER_H__
#define __LOGGER_H__
#include "defines.h"
#include "singleton.h"
#include "threadmutex.h"
#include <string>
using namespace std;
struct LogInfo
{
int nFileNum;
string strFileSuffix;
string strFileName;
};
enum
{
DEBUG = 0,
WARN,
ERROR,
INFO,
NUM_OF_LOG_LEVEL
};
class CLogger
: public CSingleton<CLogger>
{
public:
public:
int Init(const string& strLogPath, const string& strFileName);
int Log(int nLogLevel, const char* pFileName, int nLine, const char *szFormat,
);private:
DECLARE_SINGLETON_CLASS(CLogger)
CLogger();
virtual ~CLogger();
int GetFileName(int nLogLevel);
int CheckFileSize(const string& strFileName);
void GenerateFileName(string& strFileName, int nFileNum, int nLogLevel);
private:
string m_strLogPath;
string m_strFileName;
LogInfo m_szLogInfo[NUM_OF_LOG_LEVEL];
CThreadMutex m_tThreadMutex;
};
#endif /* __LOGGER_H__ */
logger.cpp
/********************************************************************
created: 2008/08/02
filename: logger.h
author: Lichuang
purpose: 實現簡易的log打印
*********************************************************************/
#include "logger.h"
#include <sys/stat.h>
static const char* g_szLogSuffix[] =
{
".debug",
".warn",
".error",
".info",
NULL
};
CLogger::CLogger()
{
}
CLogger::~CLogger()
{
}
int CLogger::Init(const string& strLogPath, const string& strFileName)
{
m_strLogPath = strLogPath;
m_strFileName = strFileName;
for (int i = DEBUG; i < NUM_OF_LOG_LEVEL; ++i)
{
m_szLogInfo[i].strFileSuffix = g_szLogSuffix[i];
if (0 > GetFileName(i))
return -1;
}
return 0;
}
int CLogger::GetFileName(int nLogLevel)
{
int i;
string strFileName;
for (i = 0; i < MAX_FILE_NUM; ++i)
{
GenerateFileName(strFileName, i, nLogLevel);
if (!CheckFileSize(strFileName))
{
break;
}
}
if (MAX_FILE_NUM == i)
{
return -1;
}
m_szLogInfo[nLogLevel].nFileNum = i;
m_szLogInfo[nLogLevel].strFileName = strFileName;
return 0;
}
int CLogger::CheckFileSize(const string& strFileName)
{
struct stat tStat;
int nRet = ::stat(strFileName.c_str(), &tStat);
if (0 == nRet && tStat.st_size > MAX_FILE_SIZE)
{
return -1;
}
else
{
return 0;
}
}
void CLogger::GenerateFileName(string& strFileName, int nFileNum, int nLogLevel)
{
char szFileNum[10];
::snprintf(szFileNum, sizeof(szFileNum), "_%02d", nFileNum);
strFileName = m_strLogPath + m_strFileName + m_szLogInfo[nLogLevel].strFileSuffix + szFileNum;
}
int CLogger::Log(int nLogLevel, const char* pFileName, int nLine, const char *szFormat,
)
{
va_list ap;
FILE *pFile;
char szTime[32];
time_t nCurrTime;
struct tm stCurrTime;
THREAD_LOCK(m_tThreadMutex);
if (0 > CheckFileSize(m_szLogInfo[nLogLevel].strFileName))
{
m_szLogInfo[nLogLevel].nFileNum = (m_szLogInfo[nLogLevel].nFileNum + 1) % MAX_FILE_NUM;
GenerateFileName(m_szLogInfo[nLogLevel].strFileName, m_szLogInfo[nLogLevel].nFileNum, nLogLevel);
}
if(NULL == (pFile = ::fopen(m_szLogInfo[nLogLevel].strFileName.c_str(), "a+")))
{
return -1;
}
::time(&nCurrTime);
::localtime_r(&nCurrTime, &stCurrTime);
::snprintf(szTime, sizeof(szTime), "%d%02d%02d %02d:%02d:%02d",
stCurrTime.tm_year+1900, stCurrTime.tm_mon+1, stCurrTime.tm_mday,
stCurrTime.tm_hour, stCurrTime.tm_min, stCurrTime.tm_sec);
::fprintf(pFile, "[%s]:[%s][%d] ", szTime, pFileName, nLine);
::va_start(ap, szFormat);
::vfprintf(pFile, szFormat, ap);
::va_end(ap);
::fprintf(pFile, "\n");
::fclose(pFile);
THREAD_UNLOCK(m_tThreadMutex);
return 0;
}
created: 2008/08/02
filename: logger.h
author: Lichuang
purpose: 實現簡易的log打印
*********************************************************************/
#include "logger.h"
#include <sys/stat.h>
static const char* g_szLogSuffix[] =
{
".debug",
".warn",
".error",
".info",
NULL
};
CLogger::CLogger()
{
}
CLogger::~CLogger()
{
}
int CLogger::Init(const string& strLogPath, const string& strFileName)
{
m_strLogPath = strLogPath;
m_strFileName = strFileName;
for (int i = DEBUG; i < NUM_OF_LOG_LEVEL; ++i)
{
m_szLogInfo[i].strFileSuffix = g_szLogSuffix[i];
if (0 > GetFileName(i))
return -1;
}
return 0;
}
int CLogger::GetFileName(int nLogLevel)
{
int i;
string strFileName;
for (i = 0; i < MAX_FILE_NUM; ++i)
{
GenerateFileName(strFileName, i, nLogLevel);
if (!CheckFileSize(strFileName))
{
break;
}
}
if (MAX_FILE_NUM == i)
{
return -1;
}
m_szLogInfo[nLogLevel].nFileNum = i;
m_szLogInfo[nLogLevel].strFileName = strFileName;
return 0;
}
int CLogger::CheckFileSize(const string& strFileName)
{
struct stat tStat;
int nRet = ::stat(strFileName.c_str(), &tStat);
if (0 == nRet && tStat.st_size > MAX_FILE_SIZE)
{
return -1;
}
else
{
return 0;
}
}
void CLogger::GenerateFileName(string& strFileName, int nFileNum, int nLogLevel)
{
char szFileNum[10];
::snprintf(szFileNum, sizeof(szFileNum), "_%02d", nFileNum);
strFileName = m_strLogPath + m_strFileName + m_szLogInfo[nLogLevel].strFileSuffix + szFileNum;
}
int CLogger::Log(int nLogLevel, const char* pFileName, int nLine, const char *szFormat,
){
va_list ap;
FILE *pFile;
char szTime[32];
time_t nCurrTime;
struct tm stCurrTime;
THREAD_LOCK(m_tThreadMutex);
if (0 > CheckFileSize(m_szLogInfo[nLogLevel].strFileName))
{
m_szLogInfo[nLogLevel].nFileNum = (m_szLogInfo[nLogLevel].nFileNum + 1) % MAX_FILE_NUM;
GenerateFileName(m_szLogInfo[nLogLevel].strFileName, m_szLogInfo[nLogLevel].nFileNum, nLogLevel);
}
if(NULL == (pFile = ::fopen(m_szLogInfo[nLogLevel].strFileName.c_str(), "a+")))
{
return -1;
}
::time(&nCurrTime);
::localtime_r(&nCurrTime, &stCurrTime);
::snprintf(szTime, sizeof(szTime), "%d%02d%02d %02d:%02d:%02d",
stCurrTime.tm_year+1900, stCurrTime.tm_mon+1, stCurrTime.tm_mday,
stCurrTime.tm_hour, stCurrTime.tm_min, stCurrTime.tm_sec);
::fprintf(pFile, "[%s]:[%s][%d] ", szTime, pFileName, nLine);
::va_start(ap, szFormat);
::vfprintf(pFile, szFormat, ap);
::va_end(ap);
::fprintf(pFile, "\n");
::fclose(pFile);
THREAD_UNLOCK(m_tThreadMutex);
return 0;
}
posted on 2008-08-05 11:37 那誰 閱讀(3018) 評論(10) 編輯 收藏 引用 所屬分類: 服務器設計 、Linux/Unix

