青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

那誰的技術博客

感興趣領域:高性能服務器編程,存儲,算法,Linux內核
隨筆 - 210, 文章 - 0, 評論 - 1183, 引用 - 0
數據加載中……

服務器公共庫開發--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:

/********************************************************************
    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__ */

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;
}


posted on 2008-08-05 11:37 那誰 閱讀(3018) 評論(10)  編輯 收藏 引用 所屬分類: 服務器設計Linux/Unix

評論

# re: 服務器公共庫開發--log系統  回復  更多評論   

log rotate 最好能加一些可配置的策略,
如允許多少log文件,文件大小超過多少rotate,用戶可定義什么時間rotate,用戶可定義log可以生存多少時間自動刪除。
log 還可以加入模塊名的參數,有的時候只想log某些模塊。
2008-08-05 13:18 | lotus

# re: 服務器公共庫開發--log系統  回復  更多評論   

試試Log4吧,Log不用自己寫
2008-08-05 13:36 | 亨德列克

# re: 服務器公共庫開發--log系統  回復  更多評論   

@lotus
這幾個配置基本都有了,除了那個用戶定義生存時間的策略我沒有做之外.另外,log模塊也沒有實現.

2008-08-05 14:27 |

# re: 服務器公共庫開發--log系統  回復  更多評論   

@亨德列克
log4cpp吧?感覺有點大....
2008-08-05 14:28 |

# re: 服務器公共庫開發--log系統  回復  更多評論   

試試log4cxx,最近出了新版本.
采用log4系列是個很好的選擇,不用擔心功能不夠用,有各種語言的綁定,大不是問題,都是設設INCLUDE路徑,LIB路徑直接用就行了.
2008-08-05 20:10 | tangxinfa

# re: 服務器公共庫開發--log系統  回復  更多評論   

所謂的 log4cxx ,完全是照抄 JAVA 的理念做的不倫不類的東西。
語言的不同核心應該是理念的不同。
C/C++ 語言最好的 log 應該是 syslog ,完全現成,完全滿足需要,完全可配置,也完全符合 KISS 標準。
記住,每個程序,只做自己改做的事情,并把事情做好。
2008-08-06 10:37 | tangfl

# re: 服務器公共庫開發--log系統  回復  更多評論   

syslog和log4xx都是封裝好的東西,如果要知其所以然,還得我們親手實踐。
各個公司可能會需要在自己的業務需求上開發自己的log基盤,所以樓主的實踐頗具價值。
2008-08-06 13:00 | 金哥

# re: 服務器公共庫開發--log系統  回復  更多評論   

每次寫log都去檢查size會不會有影響呢?
2008-08-26 11:10 | haha

# re: 服務器公共庫開發--log系統[未登錄]  回復  更多評論   

言之有理,以后會進行優化,用一個成員變量去存放文件的大小, 每次程序初始化的時候讀取文件大小到這個成員中, 每次打印log之后更新, 而不是每次去檢查文件大小.
2008-08-26 12:13 |

# re: 服務器公共庫開發--log系統  回復  更多評論   

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);
}

這里有問題吧,如果(m_szLogInfo[nLogLevel].nFileNum + 1) % MAX_FILE_NUM;這個log文件是回到0,這個文件肯定是已經達到最大存儲了,這時候還寫?
2009-03-03 20:55 | capable
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            香港成人在线视频| 欧美成人午夜剧场免费观看| 亚洲女ⅴideoshd黑人| 欧美不卡视频一区| 小黄鸭精品密入口导航| 欧美色一级片| 一本色道88久久加勒比精品 | 亚洲精品影院| 欧美 亚欧 日韩视频在线| 亚洲欧美中文另类| 国产欧美日本| 久久国产精品久久w女人spa| 亚洲网站在线观看| 欧美日韩在线播放一区| 99在线热播精品免费| 亚洲片在线资源| 欧美人交a欧美精品| 99国产麻豆精品| 亚洲精品国精品久久99热| 欧美护士18xxxxhd| 久久九九99| 亚洲高清免费| 最近中文字幕日韩精品| 欧美日韩国产综合视频在线观看中文 | 亚洲电影观看| 久久精品国产亚洲一区二区三区 | 一区二区三区欧美日韩| 精品不卡视频| 国产一区二区三区久久悠悠色av| 99热在线精品观看| 亚洲欧美网站| 欧美成人一区二区三区| 国产一区二区主播在线| 久久综合狠狠综合久久综合88| 欧美在线视频网站| 亚洲国产精品久久| 99国产精品一区| 国产欧美日韩综合一区在线播放 | 午夜久久久久久| 午夜一区在线| 亚洲大片在线观看| 99re亚洲国产精品| 国产一区二区主播在线| 91久久精品国产91性色| 国产精品国产自产拍高清av王其| 久久九九热re6这里有精品| 美腿丝袜亚洲色图| 欧美精品国产一区| 亚洲欧美日本日韩| 乱码第一页成人| 亚洲欧美一区在线| 免费欧美高清视频| 欧美亚洲视频在线观看| 欧美成人资源| 久久国产主播精品| 欧美日韩一区二区三区在线 | 国产日韩在线视频| 亚洲国产精品va在线看黑人| 国产精品三级久久久久久电影| 欧美福利影院| 国产情人节一区| 亚洲人在线视频| 欧美影院视频| 日韩一级免费| 久久久夜夜夜| 欧美诱惑福利视频| 欧美日韩亚洲国产精品| 欧美激情视频一区二区三区在线播放| 欧美性做爰毛片| 免费一级欧美片在线观看| 国产精品免费看| 亚洲精品中文字幕女同| 亚洲黄色免费| 久久九九精品99国产精品| 亚洲欧美在线免费观看| 欧美精品三区| 女女同性精品视频| 激情婷婷欧美| 久久都是精品| 久久久五月天| 国产自产2019最新不卡| 亚洲欧美另类中文字幕| 亚洲制服av| 国产精品99免费看| 一区二区三区日韩欧美精品| 国产精品99久久久久久久vr | 国产精自产拍久久久久久蜜| 夜夜嗨网站十八久久| 亚洲婷婷国产精品电影人久久| 欧美精品一区二| 91久久夜色精品国产网站| 亚洲国产精选| 欧美劲爆第一页| 亚洲精品免费网站| 宅男精品导航| 国产精品白丝jk黑袜喷水| 亚洲乱码视频| 亚洲欧美日韩精品久久亚洲区| 国产精品s色| 亚洲专区国产精品| 久久精品中文字幕一区| 激情成人av| 欧美成人a视频| 亚洲美女视频网| 午夜一区二区三区不卡视频| 国产免费一区二区三区香蕉精| 羞羞答答国产精品www一本| 久久精品一二三| 亚洲国产视频一区| 欧美精选在线| 亚洲女同同性videoxma| 久久久久成人精品| 亚洲国产网站| 欧美三级黄美女| 欧美一级理论性理论a| 你懂的一区二区| 亚洲天堂成人| 国产综合第一页| 欧美激情在线狂野欧美精品| 正在播放日韩| 免费毛片一区二区三区久久久| 亚洲精品国产欧美| 国产精品国产三级国产普通话99 | 136国产福利精品导航网址应用| 久久久久国产精品一区二区| 狠狠色噜噜狠狠狠狠色吗综合| 久久综合一区二区| 在线亚洲精品| 91久久精品国产91性色tv| 欧美日韩高清在线一区| 亚洲欧美高清| 亚洲成色777777在线观看影院| 一区二区三区视频在线看| 国产一区二区日韩| 欧美粗暴jizz性欧美20| 午夜视频一区| 亚洲精选中文字幕| 美女在线一区二区| 午夜精品久久| 一本色道久久综合亚洲精品小说| 国产一区二区欧美| 欧美午夜在线观看| 欧美成人亚洲成人| 久久国产直播| 亚洲在线观看免费| 亚洲精品一区二区三区樱花| 久久影院亚洲| 欧美一级成年大片在线观看| 日韩视频在线观看一区二区| 狠狠色丁香婷婷综合| 国产精品日韩在线观看| 欧美日韩国产成人精品| 免费观看成人网| 久久久久五月天| 欧美在线免费一级片| 亚洲一区不卡| 在线视频欧美日韩| 日韩小视频在线观看| 亚洲经典在线| 欧美激情二区三区| 久久久亚洲精品一区二区三区 | 国内精品久久久久久久影视麻豆| 欧美日韩专区| 欧美高清在线视频观看不卡| 久久久蜜桃一区二区人| 欧美一区免费视频| 性色av一区二区怡红| 亚洲砖区区免费| 亚洲图色在线| 亚洲在线观看视频| 亚洲一区二区精品视频| 亚洲小说欧美另类社区| 一区二区三区高清在线观看| 亚洲精品乱码久久久久久蜜桃91| 欧美激情精品久久久六区热门| 蜜桃av噜噜一区二区三区| 蜜桃av综合| 欧美成人一区在线| 欧美激情精品久久久久久变态| 蜜桃av综合| 欧美激情二区三区| 亚洲欧洲综合另类在线| 亚洲精品视频免费观看| 亚洲人午夜精品| 亚洲第一视频| 亚洲人成艺术| 在线视频欧美日韩| 亚洲一级二级| 欧美一区二区三区免费视| 欧美一区二区三区免费看 | 亚洲免费影视第一页| 亚洲欧美日韩一区二区在线| 午夜精品剧场| 久久久久久久精| 欧美大片在线看免费观看| 欧美精品一区二区三区蜜桃| 欧美偷拍一区二区| 国产日韩欧美综合一区| 亚洲国产导航| 亚洲一区网站|