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

            牽著老婆滿街逛

            嚴以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            開源日志系統(tǒng)log4cplus(五)

            日志系統(tǒng)的另一個基本功能就是能夠讓使用者按照自己的意愿來控制什么時候,哪些log信息可以輸出。
            如果能夠讓用戶在任意時刻設(shè)置允許輸出的LogLevel的信息就好了,log4cplus通過LogLevelManager、
            LogLog、Filter三種方式實現(xiàn)了上述功能。

            				
            ### 優(yōu)先級控制 ###
            在研究LogLevelManager之前,首先介紹一下log4cplus中l(wèi)ogger的存儲機制,在log4cplus中,所有
            logger都通過一個層次化的結(jié)構(gòu)(其實內(nèi)部是hash表)來組織的,有一個Root級別的logger,可以通
            過以下方法獲取:
            ??? Logger root = Logger::getRoot();
            ???
            用戶定義的logger都有一個名字與之對應(yīng),比如:
            ??? Logger test = Logger::getInstance("test");
            ???
            可以定義該logger的子logger:
            ??? Logger subTest = Logger::getInstance("test.subtest");
            ???
            注意Root級別的logger只有通過getRoot方法獲取,Logger::getInstance("root")獲得的是它的
            子對象而已。有了這些具有父子關(guān)系的logger之后可分別設(shè)置其LogLevel,比如:
            root.setLogLevel( ... );
            Test.setLogLevel( ... );
            subTest.setLogLevel( ... );
            				
            logger的這種父子關(guān)聯(lián)性會體現(xiàn)在優(yōu)先級控制方面,log4cplus將輸出的log信息按照LogLevel
            (從低到高)分為:
            NOT_SET_LOG_LEVEL (?? -1) :接受缺省的LogLevel,如果有父logger則繼承它的LogLevel
            ALL_LOG_LEVEL???? (??? 0) :開放所有l(wèi)og信息輸出
            TRACE_LOG_LEVEL?? (??? 0) :開放trace信息輸出(即ALL_LOG_LEVEL)
            DEBUG_LOG_LEVEL?? (10000) :開放debug信息輸出
            INFO_LOG_LEVEL??? (20000) :開放info信息輸出
            WARN_LOG_LEVEL??? (30000) :開放warning信息輸出
            ERROR_LOG_LEVEL?? (40000) :開放error信息輸出
            FATAL_LOG_LEVEL?? (50000) :開放fatal信息輸出
            OFF_LOG_LEVEL???? (60000) :關(guān)閉所有l(wèi)og信息輸出
            LogLevelManager負責設(shè)置logger的優(yōu)先級,各個logger可以通過setLogLevel設(shè)置自己的優(yōu)先級,
            當某個logger的LogLevel設(shè)置成NOT_SET_LOG_LEVEL時,該logger會繼承父logger的優(yōu)先級,另外,
            如果定義了重名的多個logger, 對其中任何一個的修改都會同時改變其它logger,我們舉例說明:
            〖例6〗
            #include "log4cplus/logger.h"
            #include "log4cplus/consoleappender.h"
            #include "log4cplus/loglevel.h"
            #include <iostream>
            using namespace std;
            using namespace log4cplus;
            int main()
            {
            ??? SharedAppenderPtr _append(new ConsoleAppender());
            ??? _append->setName("test");
            ??? Logger::getRoot().addAppender(_append);
            ??? Logger root = Logger::getRoot();
            ??? Logger test = Logger::getInstance("test");
            ??? Logger subTest = Logger::getInstance("test.subtest");
            ??? LogLevelManager& llm = getLogLevelManager();
            ??? cout << endl << "Before Setting, Default LogLevel" << endl;
            ??? LOG4CPLUS_FATAL(root, "root: " << llm.toString(root.getChainedLogLevel()))
            ??? LOG4CPLUS_FATAL(root, "test: " << llm.toString(test.getChainedLogLevel()))
            ??? LOG4CPLUS_FATAL(root, "test.subtest: " << llm.toString(subTest.getChainedLogLevel()))
            ??? cout << endl << "Setting test.subtest to WARN" << endl;
            ??? subTest.setLogLevel(WARN_LOG_LEVEL);
            ??? LOG4CPLUS_FATAL(root, "root: " << llm.toString(root.getChainedLogLevel()))
            ??? LOG4CPLUS_FATAL(root, "test: " << llm.toString(test.getChainedLogLevel()))
            ??? LOG4CPLUS_FATAL(root, "test.subtest: " << llm.toString(subTest.getChainedLogLevel()))
            ??? cout << endl << "Setting test.subtest to TRACE" << endl;
            ??? test.setLogLevel(TRACE_LOG_LEVEL);
            ??? LOG4CPLUS_FATAL(root, "root: " << llm.toString(root.getChainedLogLevel()))
            ??? LOG4CPLUS_FATAL(root, "test: " << llm.toString(test.getChainedLogLevel()))
            ??? LOG4CPLUS_FATAL(root, "test.subtest: " << llm.toString(subTest.getChainedLogLevel()))
            ??? cout << endl << "Setting test.subtest to NO_LEVEL" << endl;
            ??? subTest.setLogLevel(NOT_SET_LOG_LEVEL);
            ??? LOG4CPLUS_FATAL(root, "root: " << llm.toString(root.getChainedLogLevel()))
            ??? LOG4CPLUS_FATAL(root, "test: " << llm.toString(test.getChainedLogLevel()))
            ??? LOG4CPLUS_FATAL(root, "test.subtest: " << llm.toString(subTest.getChainedLogLevel()) << '\n')
            ??? cout << "create a logger test_bak, named \"test_\", too. " << endl;
            ??? Logger test_bak = Logger::getInstance("test");
            ??? cout << "Setting test to INFO, so test_bak also be set to INFO" << endl;
            ??? test.setLogLevel(INFO_LOG_LEVEL);
            ??? LOG4CPLUS_FATAL(root, "test: " << llm.toString(test.getChainedLogLevel()))
            ??? LOG4CPLUS_FATAL(root, "test_bak: " << llm.toString(test_bak.getChainedLogLevel()))
            ??? return 0;
            }
            輸出結(jié)果:
            Before Setting, Default LogLevel
            FATAL - root: DEBUG
            FATAL - test: DEBUG
            FATAL - test.subtest: DEBUG
            Setting test.subtest to WARN
            FATAL - root: DEBUG
            FATAL - test: DEBUG
            FATAL - test.subtest: WARN
            Setting test.subtest to TRACE
            FATAL - root: DEBUG
            FATAL - test: TRACE
            FATAL - test.subtest: WARN
            Setting test.subtest to NO_LEVEL
            FATAL - root: DEBUG
            FATAL - test: TRACE
            FATAL - test.subtest: TRACE
            create a logger test_bak, named "test_", too.
            Setting test to INFO, so test_bak also be set to INFO
            FATAL - test: INFO
            FATAL - test_bak: INFO
            				
            下面的例子演示了如何通過設(shè)置LogLevel來控制用戶的log信息輸出:
            〖例7〗
            #include "log4cplus/logger.h"
            #include "log4cplus/consoleappender.h"
            #include "log4cplus/loglevel.h"
            #include <iostream>
            using namespace std;
            using namespace log4cplus;
            void ShowMsg(void)
            {
            ??? LOG4CPLUS_TRACE(Logger::getRoot(),"info")
            ??? LOG4CPLUS_DEBUG(Logger::getRoot(),"info")
            ??? LOG4CPLUS_INFO(Logger::getRoot(),"info")
            ??? LOG4CPLUS_WARN(Logger::getRoot(),"info")
            ??? LOG4CPLUS_ERROR(Logger::getRoot(),"info")
            ??? LOG4CPLUS_FATAL(Logger::getRoot(),"info")
            }
            int main()
            {
            ??? SharedAppenderPtr _append(new ConsoleAppender());
            ??? _append->setName("test");
            ??? _append->setLayout(std::auto_ptr(new TTCCLayout()));
            ??? Logger root = Logger::getRoot();
            ??? root.addAppender(_append);
            ??? cout << endl << "all-log allowed" << endl;
            ??? root.setLogLevel(ALL_LOG_LEVEL);
            ??? ShowMsg();
            ??? cout << endl << "trace-log and above allowed" << endl;
            ??? root.setLogLevel(TRACE_LOG_LEVEL);
            ??? ShowMsg();
            ??? cout << endl << "debug-log and above allowed" << endl;
            ??? root.setLogLevel(DEBUG_LOG_LEVEL);
            ??? ShowMsg();
            ??? cout << endl << "info-log and above allowed" << endl;
            ??? root.setLogLevel(INFO_LOG_LEVEL);
            ??? ShowMsg();
            ??? cout << endl << "warn-log and above allowed" << endl;
            ??? root.setLogLevel(WARN_LOG_LEVEL);
            ??? ShowMsg();
            ??? cout << endl << "error-log and above allowed" << endl;
            ??? root.setLogLevel(ERROR_LOG_LEVEL);
            ??? ShowMsg();
            ??? cout << endl << "fatal-log and above allowed" << endl;
            ??? root.setLogLevel(FATAL_LOG_LEVEL);
            ??? ShowMsg();
            ??? cout << endl << "log disabled" << endl;
            ??? root.setLogLevel(OFF_LOG_LEVEL);
            ??? ShowMsg();
            ??? return 0;
            }
            輸出結(jié)果:
            all-log allowed
            10-17-04 10:11:40,587 [1075298944] TRACE root <> - info
            10-17-04 10:11:40,590 [1075298944] DEBUG root <> - info
            10-17-04 10:11:40,591 [1075298944] INFO root <> - info
            10-17-04 10:11:40,591 [1075298944] WARN root <> - info
            10-17-04 10:11:40,592 [1075298944] ERROR root <> - info
            10-17-04 10:11:40,592 [1075298944] FATAL root <> - info
            trace-log and above allowed
            10-17-04 10:11:40,593 [1075298944] TRACE root <> - info
            10-17-04 10:11:40,593 [1075298944] DEBUG root <> - info
            10-17-04 10:11:40,594 [1075298944] INFO root <> - info
            10-17-04 10:11:40,594 [1075298944] WARN root <> - info
            10-17-04 10:11:40,594 [1075298944] ERROR root <> - info
            10-17-04 10:11:40,594 [1075298944] FATAL root <> - info
            debug-log and above allowed
            10-17-04 10:11:40,595 [1075298944] DEBUG root <> - info
            10-17-04 10:11:40,595 [1075298944] INFO root <> - info
            10-17-04 10:11:40,596 [1075298944] WARN root <> - info
            10-17-04 10:11:40,596 [1075298944] ERROR root <> - info
            10-17-04 10:11:40,596 [1075298944] FATAL root <> - info
            info-log and above allowed
            10-17-04 10:11:40,597 [1075298944] INFO root <> - info
            10-17-04 10:11:40,597 [1075298944] WARN root <> - info
            10-17-04 10:11:40,597 [1075298944] ERROR root <> - info
            10-17-04 10:11:40,598 [1075298944] FATAL root <> - info
            warn-log and above allowed
            10-17-04 10:11:40,598 [1075298944] WARN root <> - info
            10-17-04 10:11:40,598 [1075298944] ERROR root <> - info
            10-17-04 10:11:40,599 [1075298944] FATAL root <> - info
            error-log and above allowed
            10-17-04 10:11:40,599 [1075298944] ERROR root <> - info
            10-17-04 10:11:40,600 [1075298944] FATAL root <> - info
            fatal-log and above allowed
            10-17-04 10:11:40,600 [1075298944] FATAL root <> - info
            log disabled
            ?
            用戶也可以自行定義LogLevel,操作比較簡單,首先要定義LEVEL值,比如HELLO_LOG_LEVEL定義如下:
            /* DEBUG_LOG_LEVEL? < HELLO_LOG_LEVEL < INFO_LOG_LEVEL */
            const LogLevel HELLO_LOG_LEVEL = 15000;
            然后定義以下宏即可:
            /* define MACRO LOG4CPLUS_HELLO */
            #define LOG4CPLUS_HELLO(logger, logEvent) \
            ??? if(logger.isEnabledFor(HELLO_LOG_LEVEL)) { \
            ??????? log4cplus::tostringstream _log4cplus_buf; \
            ??????? _log4cplus_buf << logEvent; \
            ?logger.forcedLog(HELLO_LOG_LEVEL, _log4cplus_buf.str(), __FILE__, __LINE__); \
            ??? }
            不過log4cplus沒有提供給用戶一個接口來實現(xiàn)LEVEL值與字符串的轉(zhuǎn)換,所以當帶格式輸出LogLevel字符
            串時候會顯示"UNKNOWN", 不夠理想。比如用TTCCLayout控制輸出的結(jié)果可能會如下所示:
            10-17-04 11:17:51,124 [1075298944] UNKNOWN root <> - info
            而不是期望的以下結(jié)果:
            10-17-04 11:17:51,124 [1075298944] HELLO root <> - info
            要想實現(xiàn)第二種結(jié)果,按照log4cplus現(xiàn)有的接口機制,只能改其源代碼后重新編譯,方法是在loglevel.cxx
            中加入:
            #define _HELLO_STRING LOG4CPLUS_TEXT("HELLO")
            然后修改log4cplus::tstring? defaultLogLevelToStringMethod(LogLevel ll)函數(shù),增加一個判斷:
            case HELLO_LOG_LEVEL:??? return _HELLO_STRING;
            重新編譯log4cplus源代碼后生成庫文件,再使用時即可實現(xiàn)滿意效果。
            				
            ### 調(diào)試模式 ###
            即通過loglog來控制輸出調(diào)試、警告或錯誤信息,見例4,這里不再贅述。
            ?
            ### 基于腳本配置來過濾log信息 ###
            除了通過程序?qū)崿F(xiàn)對log環(huán)境的配置之外,log4cplus通過PropertyConfigurator類實現(xiàn)了基于腳本配置的功能。
            通過腳本可以完成對logger、appender和layout的配置,因此可以解決怎樣輸出,輸出到哪里的問題,我將在
            全文的最后一部分中提到多線程環(huán)境中如何利用腳本配置來配合實現(xiàn)性能測試,本節(jié)將重點介紹基腳本實現(xiàn)過
            濾log信息的功能。
            首先簡單介紹一下腳本的語法規(guī)則:
            包括Appender的配置語法和logger的配置語法,其中:
            1.Appender的配置語法:
            (1)設(shè)置名稱:
            /*設(shè)置方法*/
            log4cplus.appender.appenderName=fully.qualified.name.of.appender.class
            例如(列舉了所有可能的Appender,其中SocketAppender后面會講到):
            log4cplus.appender.append_1=log4cplus::ConsoleAppender
            log4cplus.appender.append_2=log4cplus::FileAppender
            log4cplus.appender.append_3=log4cplus::RollingFileAppender
            log4cplus.appender.append_4=log4cplus::DailyRollingFileAppender
            log4cplus.appender.append_4=log4cplus::SocketAppender
            (2)設(shè)置Filter:
            包括選擇過濾器和設(shè)置過濾條件,可選擇的過濾器包括:LogLevelMatchFilter、LogLevelRangeFilter、
            和StringMatchFilter:
            對LogLevelMatchFilter來說,過濾條件包括LogLevelToMatch和AcceptOnMatch(true|false), 只有
            當log信息的LogLevel值與LogLevelToMatch相同,且AcceptOnMatch為true時才會匹配。
            LogLevelRangeFilter來說,過濾條件包括LogLevelMin、LogLevelMax和AcceptOnMatch,只有當log信息
            的LogLevel在LogLevelMin、LogLevelMax之間同時AcceptOnMatch為true時才會匹配。
            對StringMatchFilter來說,過濾條件包括StringToMatch和AcceptOnMatch,只有當log信息的LogLevel值
            與StringToMatch對應(yīng)的LogLevel值與相同, 且AcceptOnMatch為true時會匹配。
            				
            過濾條件處理機制類似于IPTABLE的Responsibility chain,(即先deny、再allow)不過執(zhí)行順序剛好相反,
            后寫的條件會被先執(zhí)行,比如:
            log4cplus.appender.append_1.filters.1=log4cplus::spi::LogLevelMatchFilter
            log4cplus.appender.append_1.filters.1.LogLevelToMatch=TRACE
            log4cplus.appender.append_1.filters.1.AcceptOnMatch=true
            #log4cplus.appender.append_1.filters.2=log4cplus::spi::DenyAllFilter
            會首先執(zhí)行filters.2的過濾條件,關(guān)閉所有過濾器,然后執(zhí)行filters.1,僅匹配TRACE信息。
            (3)設(shè)置Layout
            可以選擇不設(shè)置、TTCCLayout、或PatternLayout
            如果不設(shè)置,會輸出簡單格式的log信息。
            設(shè)置TTCCLayout如下所示:
            log4cplus.appender.ALL_MSGS.layout=log4cplus::TTCCLayout
            設(shè)置PatternLayout如下所示:
            log4cplus.appender.append_1.layout=log4cplus::PatternLayout
            log4cplus.appender.append_1.layout.ConversionPattern=%d{%m/%d/%y %H:%M:%S,%Q} [%t] %-5p - %m%n
            				
            2.logger的配置語法
            包括rootLogger和non-root logger。
            對于rootLogger來說:
            log4cplus.rootLogger=[LogLevel], appenderName, appenderName, ...
            對于non-root logger來說:
            log4cplus.logger.logger_name=[LogLevel|INHERITED], appenderName, appenderName, ...
            				
            腳本方式使用起來非常簡單,只要首先加載配置即可(urconfig.properties是自行定義的配置文件):
            PropertyConfigurator::doConfigure("urconfig.properties");
            				
            下面我們通過例子體會一下log4cplus強大的基于腳本過濾log信息的功能。
            				
            〖例8〗
            /*
            ?*??? urconfig.properties
            ?*/
            log4cplus.rootLogger=TRACE, ALL_MSGS, TRACE_MSGS, DEBUG_INFO_MSGS, FATAL_MSGS
            log4cplus.appender.ALL_MSGS=log4cplus::RollingFileAppender
            log4cplus.appender.ALL_MSGS.File=all_msgs.log
            log4cplus.appender.ALL_MSGS.layout=log4cplus::TTCCLayout
            log4cplus.appender.TRACE_MSGS=log4cplus::RollingFileAppender
            log4cplus.appender.TRACE_MSGS.File=trace_msgs.log
            log4cplus.appender.TRACE_MSGS.layout=log4cplus::TTCCLayout
            log4cplus.appender.TRACE_MSGS.filters.1=log4cplus::spi::LogLevelMatchFilter
            log4cplus.appender.TRACE_MSGS.filters.1.LogLevelToMatch=TRACE
            log4cplus.appender.TRACE_MSGS.filters.1.AcceptOnMatch=true
            log4cplus.appender.TRACE_MSGS.filters.2=log4cplus::spi::DenyAllFilter
            log4cplus.appender.DEBUG_INFO_MSGS=log4cplus::RollingFileAppender
            log4cplus.appender.DEBUG_INFO_MSGS.File=debug_info_msgs.log
            log4cplus.appender.DEBUG_INFO_MSGS.layout=log4cplus::TTCCLayout
            log4cplus.appender.DEBUG_INFO_MSGS.filters.1=log4cplus::spi::LogLevelRangeFilter
            log4cplus.appender.DEBUG_INFO_MSGS.filters.1.LogLevelMin=DEBUG
            log4cplus.appender.DEBUG_INFO_MSGS.filters.1.LogLevelMax=INFO
            log4cplus.appender.DEBUG_INFO_MSGS.filters.1.AcceptOnMatch=true
            log4cplus.appender.DEBUG_INFO_MSGS.filters.2=log4cplus::spi::DenyAllFilter
            log4cplus.appender.FATAL_MSGS=log4cplus::RollingFileAppender
            log4cplus.appender.FATAL_MSGS.File=fatal_msgs.log
            log4cplus.appender.FATAL_MSGS.layout=log4cplus::TTCCLayout
            log4cplus.appender.FATAL_MSGS.filters.1=log4cplus::spi::StringMatchFilter
            log4cplus.appender.FATAL_MSGS.filters.1.StringToMatch=FATAL
            log4cplus.appender.FATAL_MSGS.filters.1.AcceptOnMatch=true
            log4cplus.appender.FATAL_MSGS.filters.2=log4cplus::spi::DenyAllFilter
            				
            /*
            ?*??? main.cpp
            ?*/
            #include <log4cplus/logger.h>
            #include <log4cplus/configurator.h>
            #include <log4cplus/helpers/stringhelper.h>
            using namespace log4cplus;
            static Logger logger = Logger::getInstance("log");
            void printDebug()
            {
            ??? LOG4CPLUS_TRACE_METHOD(logger, "::printDebug()");
            ??? LOG4CPLUS_DEBUG(logger, "This is a DEBUG message");
            ??? LOG4CPLUS_INFO(logger, "This is a INFO message");
            ??? LOG4CPLUS_WARN(logger, "This is a WARN message");
            ??? LOG4CPLUS_ERROR(logger, "This is a ERROR message");
            ??? LOG4CPLUS_FATAL(logger, "This is a FATAL message");
            }
            int main()
            {
            ??? Logger root = Logger::getRoot();
            ??? PropertyConfigurator::doConfigure("urconfig.properties");
            ??? printDebug();
            ??? return 0;
            }
            運行結(jié)果:
            1. all_msgs.log
            10-17-04 14:55:25,858 [1075298944] TRACE log <> - ENTER: ::printDebug()
            10-17-04 14:55:25,871 [1075298944] DEBUG log <> - This is a DEBUG message
            10-17-04 14:55:25,873 [1075298944] INFO log <> - This is a INFO message
            10-17-04 14:55:25,873 [1075298944] WARN log <> - This is a WARN message
            10-17-04 14:55:25,874 [1075298944] ERROR log <> - This is a ERROR message
            10-17-04 14:55:25,874 [1075298944] FATAL log <> - This is a FATAL message
            10-17-04 14:55:25,875 [1075298944] TRACE log <> - EXIT:? ::printDebug()
            2. trace_msgs.log
            10-17-04 14:55:25,858 [1075298944] TRACE log <> - ENTER: ::printDebug()
            10-17-04 14:55:25,875 [1075298944] TRACE log <> - EXIT:? ::printDebug()
            3. debug_info_msgs.log
            10-17-04 14:55:25,871 [1075298944] DEBUG log <> - This is a DEBUG message
            10-17-04 14:55:25,873 [1075298944] INFO log <> - This is a INFO message
            4. fatal_msgs.log
            10-17-04 14:55:25,874 [1075298944] FATAL log <> - This is a FATAL message
            ?
            本部分詳細介紹了如何有選擇地控制log信息的輸出,最后一部分我們將介紹一下多線程、
            和C/S模式下該如何操作,順便提一下NDC的概念。

            posted on 2006-08-26 04:50 楊粼波 閱讀(8267) 評論(0)  編輯 收藏 引用 所屬分類: Windows編程Linux編程

            99久久婷婷免费国产综合精品| 久久精品成人影院| 欧美激情精品久久久久久久| 青青国产成人久久91网| 狠狠色丁香久久综合五月| 精品国产乱码久久久久久1区2区 | 模特私拍国产精品久久| 色婷婷久久综合中文久久一本| 久久99精品久久久久久噜噜| 国产福利电影一区二区三区久久老子无码午夜伦不 | 一本一本久久aa综合精品| 日日狠狠久久偷偷色综合免费 | 久久精品国产99国产精品导航| 亚洲欧美日韩久久精品| 亚洲精品国产第一综合99久久| 久久久久久国产精品美女| 人妻无码αv中文字幕久久| 久久99热只有频精品8| 亚洲成色999久久网站| 日本精品久久久久久久久免费| 婷婷久久精品国产| 日产精品99久久久久久| 国产精品久久久福利| 99久久99久久精品国产| 久久精品中文字幕大胸| 国产精品一区二区久久不卡| 一级做a爰片久久毛片人呢| 欧美国产成人久久精品| 久久偷看各类wc女厕嘘嘘| 国内精品久久久久久久久电影网 | 久久婷婷国产剧情内射白浆| 蜜臀av性久久久久蜜臀aⅴ| 99久久精品免费| 亚洲AV日韩精品久久久久久久| 久久se精品一区精品二区| 一级a性色生活片久久无| 久久精品国产亚洲一区二区| 欧美一级久久久久久久大片 | 久久综合狠狠综合久久| 欧美性大战久久久久久| 国产精品久久久久久福利漫画|