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

            那誰的技術博客

            感興趣領域:高性能服務器編程,存儲,算法,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 那誰 閱讀(2991) 評論(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
            精品久久久久久中文字幕大豆网| 亚洲国产精品狼友中文久久久| 久久不见久久见免费视频7| 久久久久久亚洲精品成人| 久久99精品国产一区二区三区| 精品久久久久久国产免费了| 久久无码精品一区二区三区| 激情伊人五月天久久综合| 久久久久综合国产欧美一区二区| 少妇内射兰兰久久| 久久中文精品无码中文字幕| 久久久久久午夜成人影院| 日本久久中文字幕| 丁香久久婷婷国产午夜视频| 伊人久久大香线蕉av一区| 久久99精品久久久久久不卡| 色诱久久久久综合网ywww| 亚洲国产精品综合久久网络 | 国产激情久久久久影院老熟女免费| 久久这里有精品视频| 久久免费精品一区二区| 无码国内精品久久人妻| 久久久精品人妻无码专区不卡 | 无码国产69精品久久久久网站| 久久无码国产| 久久久久国产亚洲AV麻豆| 99久久国产综合精品麻豆| 亚洲精品无码专区久久久| 久久亚洲熟女cc98cm| 久久久久久久波多野结衣高潮 | 国产精品久久久久久吹潮| 国产亚洲美女精品久久久2020| 久久99九九国产免费看小说| 久久影院亚洲一区| 亚洲国产成人精品女人久久久| 一级做a爰片久久毛片16| 嫩草影院久久国产精品| 久久久久国产精品| 久久国产美女免费观看精品| 久久天天躁狠狠躁夜夜2020老熟妇| 韩国三级中文字幕hd久久精品|