• <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>

            那誰(shuí)的技術(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í), 也可以通過(guò)宏來(lái)開啟DEBUG,WARN的log.
            4) 在向文件打印log時(shí), 支持多線程, 同樣的, 這個(gè)也是可以配置的.

            分為三個(gè)文件,log.h是對(duì)外的接口, 提供對(duì)文件打印log和對(duì)標(biāo)準(zhǔn)輸出打印log的簡(jiǎn)易封裝, 具體使用哪種方式, 可以通過(guò)宏進(jìn)行配置;logger.h和logger.cpp是對(duì)文件進(jìn)行打印的類封裝, 是一個(gè)單件類, 因此繼承自前面提過(guò)的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 那誰(shuí) 閱讀(3000) 評(píng)論(10)  編輯 收藏 引用 所屬分類: 服務(wù)器設(shè)計(jì)Linux/Unix

            評(píng)論

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

            log rotate 最好能加一些可配置的策略,
            如允許多少log文件,文件大小超過(guò)多少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)心功能不夠用,有各種語(yǔ)言的綁定,大不是問(wèn)題,都是設(shè)設(shè)INCLUDE路徑,LIB路徑直接用就行了.
            2008-08-05 20:10 | tangxinfa

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

            所謂的 log4cxx ,完全是照抄 JAVA 的理念做的不倫不類的東西。
            語(yǔ)言的不同核心應(yīng)該是理念的不同。
            C/C++ 語(yǔ)言最好的 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);
            }

            這里有問(wèn)題吧,如果(m_szLogInfo[nLogLevel].nFileNum + 1) % MAX_FILE_NUM;這個(gè)log文件是回到0,這個(gè)文件肯定是已經(jīng)達(dá)到最大存儲(chǔ)了,這時(shí)候還寫?
            2009-03-03 20:55 | capable
            婷婷久久综合九色综合绿巨人| 久久久久久午夜精品| 亚洲AV无码1区2区久久| 亚洲av成人无码久久精品| 精品国产VA久久久久久久冰| 一本色道久久88加勒比—综合| 久久国产精品二国产精品| 思思久久好好热精品国产| 久久精品国产亚洲AV无码娇色 | 色欲综合久久躁天天躁| 精品久久久久久久久免费影院| 久久精品国产2020| 国产精品久久久久乳精品爆 | 欧美激情精品久久久久久| 久久久午夜精品福利内容| 日本久久久久久中文字幕| 久久频这里精品99香蕉久| 伊人久久免费视频| 久久99国产综合精品| 亚洲欧洲精品成人久久曰影片 | 亚洲狠狠婷婷综合久久蜜芽| 精品午夜久久福利大片| 国产毛片欧美毛片久久久| 久久久久99精品成人片| 麻豆精品久久久一区二区| 亚洲精品白浆高清久久久久久 | 久久亚洲2019中文字幕| 久久精品国产只有精品2020| 人妻丰满AV无码久久不卡| 精品久久久久成人码免费动漫 | 久久久SS麻豆欧美国产日韩| 久久av免费天堂小草播放| 2022年国产精品久久久久| 久久久一本精品99久久精品88| 国产成人精品综合久久久久| 亚洲国产香蕉人人爽成AV片久久 | 成人久久久观看免费毛片| 无码人妻少妇久久中文字幕蜜桃| 久久久亚洲欧洲日产国码是AV| 九九精品久久久久久噜噜| 亚洲国产天堂久久综合|