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

那誰的技術(shù)博客

感興趣領(lǐng)域:高性能服務(wù)器編程,存儲(chǔ),算法,Linux內(nèi)核
隨筆 - 210, 文章 - 0, 評(píng)論 - 1183, 引用 - 0
數(shù)據(jù)加載中……

服務(wù)器公共庫(kù)開發(fā)--log系統(tǒng)

實(shí)現(xiàn)了簡(jiǎn)易的log打印,有以下的特點(diǎn):
1) 支持向標(biāo)準(zhǔn)輸出或者文件打印log
2) 向文件打印log時(shí)限制log文件的大小, 同時(shí), 如果在文件大小超出范圍的時(shí)候, 可以選擇下一個(gè)文件進(jìn)行打印.在這里, 文件大小和文件的數(shù)量都是可以配置的.
3) 支持分級(jí)別打印, 目前分的級(jí)別有DEBUG,ERROR,WARN,INFO這幾種, 在打印時(shí), 也可以通過宏來開啟DEBUG,WARN的log.
4) 在向文件打印log時(shí), 支持多線程, 同樣的, 這個(gè)也是可以配置的.

分為三個(gè)文件,log.h是對(duì)外的接口, 提供對(duì)文件打印log和對(duì)標(biāo)準(zhǔn)輸出打印log的簡(jiǎn)易封裝, 具體使用哪種方式, 可以通過宏進(jìn)行配置;logger.h和logger.cpp是對(duì)文件進(jìn)行打印的類封裝, 是一個(gè)單件類, 因此繼承自前面提過的singleton類.

log.h:

/********************************************************************
    created:    2008/08/02
    filename:   log.h    
    author:        Lichuang
                
    purpose:    log模塊的對(duì)外接口, 可以根據(jù)宏將log打印到文件或者標(biāo)準(zhǔn)
                輸出
********************************************************************
*/

#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:    實(shí)現(xiàn)簡(jiǎn)易的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:    實(shí)現(xiàn)簡(jiǎn)易的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 那誰 閱讀(3013) 評(píng)論(10)  編輯 收藏 引用 所屬分類: 服務(wù)器設(shè)計(jì)Linux/Unix

評(píng)論

# re: 服務(wù)器公共庫(kù)開發(fā)--log系統(tǒng)  回復(fù)  更多評(píng)論   

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

# re: 服務(wù)器公共庫(kù)開發(fā)--log系統(tǒng)  回復(fù)  更多評(píng)論   

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

# re: 服務(wù)器公共庫(kù)開發(fā)--log系統(tǒng)  回復(fù)  更多評(píng)論   

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

2008-08-05 14:27 | 創(chuàng)

# re: 服務(wù)器公共庫(kù)開發(fā)--log系統(tǒng)  回復(fù)  更多評(píng)論   

@亨德列克
log4cpp吧?感覺有點(diǎn)大....
2008-08-05 14:28 | 創(chuàng)

# re: 服務(wù)器公共庫(kù)開發(fā)--log系統(tǒng)  回復(fù)  更多評(píng)論   

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

# re: 服務(wù)器公共庫(kù)開發(fā)--log系統(tǒng)  回復(fù)  更多評(píng)論   

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

# re: 服務(wù)器公共庫(kù)開發(fā)--log系統(tǒng)  回復(fù)  更多評(píng)論   

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

# re: 服務(wù)器公共庫(kù)開發(fā)--log系統(tǒng)  回復(fù)  更多評(píng)論   

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

# re: 服務(wù)器公共庫(kù)開發(fā)--log系統(tǒng)[未登錄]  回復(fù)  更多評(píng)論   

言之有理,以后會(huì)進(jìn)行優(yōu)化,用一個(gè)成員變量去存放文件的大小, 每次程序初始化的時(shí)候讀取文件大小到這個(gè)成員中, 每次打印log之后更新, 而不是每次去檢查文件大小.
2008-08-26 12:13 | 創(chuàng)

# re: 服務(wù)器公共庫(kù)開發(fā)--log系統(tǒng)  回復(fù)  更多評(píng)論   

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;這個(gè)log文件是回到0,這個(gè)文件肯定是已經(jīng)達(dá)到最大存儲(chǔ)了,這時(shí)候還寫?
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>
            亚洲激情中文1区| 久久se精品一区二区| 免费观看一区| 美女脱光内衣内裤视频久久网站| 国产欧美日韩免费| 久久不射2019中文字幕| 久久精品亚洲精品| 亚洲日本aⅴ片在线观看香蕉| 欧美国产日韩在线| 欧美日韩亚洲视频一区| 午夜精品国产| 久久经典综合| 西西裸体人体做爰大胆久久久| 免费成人av资源网| 小嫩嫩精品导航| 亚洲欧美精品一区| 一区二区三区在线观看国产| 亚洲国产一区二区精品专区| 欧美日本高清| 久久久免费观看视频| 免费在线欧美黄色| 亚洲综合成人在线| 久久亚洲一区二区三区四区| 亚洲精品影视在线观看| 亚洲欧美激情诱惑| 亚洲人在线视频| 欧美亚洲一区三区| 一本色道久久88亚洲综合88| 性久久久久久久| 99日韩精品| 久久午夜羞羞影院免费观看| 亚洲欧美中文另类| 欧美福利在线| 久久蜜臀精品av| 国产精品免费网站在线观看| 欧美刺激午夜性久久久久久久| 国产精品久久久久久久久久久久久| 麻豆成人av| 国产精品亚洲一区| 日韩视频一区二区在线观看| 亚洲第一偷拍| 久久国产精品久久久久久| 亚洲视频精选在线| 欧美成人免费在线观看| 久久三级视频| 国产视频一区二区在线观看 | 国产亚洲成av人在线观看导航 | 亚洲一级黄色| 免费观看久久久4p| 麻豆精品一区二区综合av| 国产精品日本一区二区| 亚洲另类自拍| 亚洲另类在线一区| 美女精品自拍一二三四| 久久综合一区| 精品福利电影| 久久九九99| 麻豆精品传媒视频| 红桃视频亚洲| 久久久一二三| 麻豆成人在线播放| 在线观看91久久久久久| 欧美一级免费视频| 久久久久88色偷偷免费| 国精产品99永久一区一区| 亚洲在线播放| 香蕉久久夜色| 国产精品一级久久久| 亚洲一区二区三区色| 欧美一区二区在线看| 国产精品入口麻豆原神| 亚洲在线成人| 久久精品30| 在线看片日韩| 欧美成人资源网| 狠狠色综合播放一区二区| 久久欧美中文字幕| 国产免费亚洲高清| 久久99在线观看| 狼人天天伊人久久| 亚洲三级影片| 欧美视频久久| 欧美一级大片在线观看| 免费成人性网站| av成人免费| 国产伦精品一区二区三区免费 | 蜜臀av性久久久久蜜臀aⅴ四虎| 1000部国产精品成人观看| 欧美激情a∨在线视频播放| 一本色道久久综合狠狠躁篇怎么玩 | 久久婷婷亚洲| 日韩一区二区久久| 久久久久久久一区二区| 亚洲黄色三级| 国产精品乱码一区二三区小蝌蚪| 欧美一区二区三区的| 欧美成人在线免费观看| 亚洲自拍偷拍福利| 一区二区三区在线视频免费观看 | 欧美一区影院| 亚洲精品女人| 午夜一区不卡| 亚洲精品视频在线看| 国产欧美一区在线| 欧美激情精品久久久久久蜜臀| 亚洲一区二区影院| 亚洲欧洲精品一区二区| 久久激情网站| 一区二区三区高清在线观看| 国产一区二区精品| 欧美日韩综合在线| 免费久久99精品国产| 亚洲欧美日本日韩| 亚洲伦理在线免费看| 久久综合国产精品| 羞羞色国产精品| 正在播放欧美视频| 亚洲黄色大片| 伊人狠狠色j香婷婷综合| 国产精品久久久久久久久久久久久久 | 久久久水蜜桃| 午夜在线成人av| 国产精品99久久久久久久久| 亚洲第一网站| 男女视频一区二区| 久久天天躁夜夜躁狠狠躁2022| 午夜电影亚洲| 亚洲免费视频中文字幕| 亚洲理论电影网| 亚洲欧洲精品一区二区三区不卡 | 开元免费观看欧美电视剧网站| 午夜在线视频一区二区区别| 在线亚洲欧美| 欧美日韩你懂的| 亚洲婷婷国产精品电影人久久| 亚洲国产裸拍裸体视频在线观看乱了中文 | 99精品视频免费观看| 在线日韩一区二区| 精品成人一区二区三区| 国产一区二区三区网站 | 欧美成人一区在线| 美女亚洲精品| 免费国产一区二区| 欧美成人一区二区三区| 欧美激情综合色综合啪啪| 欧美xx69| 欧美视频在线观看视频极品| 欧美色中文字幕| 国产精品成人免费视频| 国产精品美女黄网| 国产日产精品一区二区三区四区的观看方式 | 久久久久一区二区三区| 免费成人黄色| 亚洲二区在线视频| 最近中文字幕日韩精品 | 中国亚洲黄色| 香蕉av777xxx色综合一区| 久久精品成人| 欧美成人嫩草网站| 欧美午夜不卡影院在线观看完整版免费| 欧美国产日韩二区| 欧美新色视频| 国产视频一区在线| 亚洲激情不卡| 亚洲一区在线播放| 久久嫩草精品久久久精品| 麻豆91精品91久久久的内涵| 欧美韩日视频| 亚洲视频在线一区| 久久精品视频导航| 欧美久久一区| 国产午夜精品美女视频明星a级| 在线成人免费观看| 亚洲深夜影院| 久久日韩粉嫩一区二区三区| 亚洲欧洲精品一区二区精品久久久| 一区二区高清视频| 久久九九免费| 欧美色道久久88综合亚洲精品| 国产日韩欧美黄色| 99国产精品自拍| 久久久久久久久岛国免费| 亚洲国产美女精品久久久久∴| 一区二区激情视频| 久久夜色精品| 国产精品有限公司| 99精品国产在热久久下载| 久久精品道一区二区三区| 亚洲七七久久综合桃花剧情介绍| 亚洲欧美日韩精品久久| 欧美区国产区| 亚洲激情另类| 久久久久国产一区二区| 一区二区三区视频在线播放| 久久精品在这里| 国产婷婷色一区二区三区四区| 国产精品99久久久久久久久| 欧美国产日韩视频| 欧美在线影院| 国产精品视频免费在线观看|