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

那誰的技術博客

感興趣領域:高性能服務器編程,存儲,算法,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>
            国产精品素人视频| 免费久久99精品国产自| 国产精品一区二区三区免费观看| 欧美成人中文字幕在线| 久久久亚洲人| 久久深夜福利免费观看| 久久亚洲一区二区三区四区| 老司机午夜精品视频在线观看| 久久亚洲春色中文字幕久久久| 久久野战av| 欧美日韩久久不卡| 国产精品日韩一区二区三区| 国产区在线观看成人精品| 好吊色欧美一区二区三区四区| 影音先锋在线一区| 亚洲美女视频在线观看| 亚洲午夜激情在线| 久久精品99| 亚洲国产99精品国自产| 欧美华人在线视频| 亚洲欧洲日本一区二区三区| 一区二区三区av| 欧美一区二区精美| 欧美成人精品在线| 国产精品美女久久久| 国产亚洲人成a一在线v站| 亚洲啪啪91| 999亚洲国产精| 久久欧美中文字幕| 欧美激情第10页| 国产日韩欧美不卡在线| 亚洲黄色影院| 久久免费黄色| 小辣椒精品导航| 久久国产精品亚洲77777| 美国三级日本三级久久99| 亚洲精品在线一区二区| 亚洲自拍电影| 欧美顶级艳妇交换群宴| 国产精品一区二区在线观看网站| 在线观看不卡| 欧美一区二区免费视频| 亚洲夫妻自拍| 久久www成人_看片免费不卡| 欧美日韩伊人| 韩国精品主播一区二区在线观看| 亚洲视频网站在线观看| 毛片av中文字幕一区二区| 亚洲综合好骚| 国产精品久久久久91| 亚洲乱码国产乱码精品精天堂| 久久成人免费电影| 日韩午夜在线| 欧美精品在线播放| 亚洲片区在线| 欧美大学生性色视频| 久久精品二区三区| 国产香蕉久久精品综合网| 亚洲欧美日本视频在线观看| 日韩午夜在线观看视频| 欧美精品在线一区| 日韩一区二区电影网| 欧美成人免费播放| 久久精品亚洲一区二区三区浴池 | 蜜臀91精品一区二区三区| 亚洲在线网站| 国产精品亚洲综合色区韩国| 午夜国产不卡在线观看视频| 一本色道久久综合亚洲精品高清| 欧美精品久久天天躁| 亚洲三级观看| 亚洲精品久久久久久久久| 欧美日本三区| 午夜精品一区二区三区在线视| 亚洲在线不卡| 极品日韩av| 亚洲欧洲一区二区三区在线观看| 欧美国产1区2区| 亚洲伊人网站| 午夜精品影院| 伊人久久av导航| 亚洲精品国产欧美| 国产精品午夜视频| 欧美吻胸吃奶大尺度电影| 欧美网站在线观看| 欧美一区午夜精品| 欧美专区福利在线| 亚洲大片在线观看| 亚洲三级免费电影| 国产欧美va欧美va香蕉在| 巨乳诱惑日韩免费av| 欧美a级片网| 午夜一区二区三视频在线观看| 欧美专区日韩视频| 一区二区av| 亚洲系列中文字幕| 国产一区二区三区av电影| 免费欧美高清视频| 欧美日韩精品一区二区在线播放 | 欧美一区二区三区啪啪| 韩国精品在线观看| 噜噜噜噜噜久久久久久91| 欧美 日韩 国产一区二区在线视频 | 亚洲欧美一区二区三区久久| 欧美性淫爽ww久久久久无| 欧美一区二区网站| 久久免费高清| 欧美在线亚洲在线| 六月丁香综合| 亚洲天堂网在线观看| 亚洲欧美日韩精品综合在线观看| 国产欧美一区二区三区国产幕精品| 久久精品国产99国产精品澳门| 亚洲午夜av电影| 亚洲精品乱码久久久久久蜜桃麻豆 | 日韩系列在线| 国产主播一区二区三区| 亚洲福利在线观看| 国产精品视频最多的网站| 欧美11—12娇小xxxx| 久久九九免费| 久久高清免费观看| 欧美国产欧美亚洲国产日韩mv天天看完整 | 免费观看在线综合色| 欧美日本免费| 久久天堂精品| 久久米奇亚洲| 久久人人超碰| 国产精品高清网站| 欧美高清视频在线播放| 国产精品久久久久久久午夜片| 欧美fxxxxxx另类| 国产精品久久久久9999| 亚洲国产精选| 国产日韩亚洲欧美精品| 亚洲精品久久久久中文字幕欢迎你 | 亚洲日本理论电影| 欧美在线视频不卡| 亚洲午夜久久久久久久久电影院| 久久久久久久网| 欧美主播一区二区三区| 欧美性大战久久久久久久蜜臀| 久久综合色天天久久综合图片| 亚洲一区二区黄色| 亚洲国产精品高清久久久| 亚洲视频精品在线| 久久久精品国产一区二区三区| 亚洲一区二区黄| 欧美国产精品中文字幕| 欧美福利一区二区| 国内揄拍国内精品久久| 亚洲欧美日韩高清| 亚洲精品午夜| 欧美无砖砖区免费| 一本色道久久综合亚洲精品小说| 亚洲国产精品久久久久秋霞影院| 亚洲欧美精品在线观看| 亚洲欧美日韩在线高清直播| 欧美天天视频| 亚洲午夜激情免费视频| 亚洲第一天堂av| 久久亚洲不卡| 亚洲大片av| 国内精品国语自产拍在线观看| 久久久久免费观看| 免费视频最近日韩| 亚洲国产综合视频在线观看 | 亚洲一级在线| 亚洲欧美日韩在线不卡| 欧美午夜精品理论片a级按摩| 欧美激情精品| 欧美在线免费观看亚洲| 亚洲尤物视频网| 国产精品亚洲综合久久| 亚洲国产精品成人一区二区| 欧美高清视频一区| 国产精品高清在线| 制服丝袜亚洲播放| 午夜欧美精品久久久久久久| 久久人人97超碰人人澡爱香蕉 | 午夜伦欧美伦电影理论片| 欧美无砖砖区免费| 亚洲一区二区免费在线| 欧美伊人久久久久久午夜久久久久| 国产精品国色综合久久| 先锋影音网一区二区| 久久综合色天天久久综合图片| 国产视频久久久久久久| 欧美精品激情在线观看| 日韩天堂av| 久久久久久久久一区二区| 亚洲国产精品精华液2区45| 欧美视频专区一二在线观看| 午夜亚洲性色福利视频| 欧美激情亚洲一区| 欧美成人69| 久久国产婷婷国产香蕉| 亚洲日韩欧美一区二区在线| 午夜精品久久久99热福利| 亚洲第一免费播放区|