<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 56, comments - 77, trackbacks - 0, articles - 1
      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

    Log 問題域

    Posted on 2010-07-06 23:15 切爾斯基 閱讀(1950) 評(píng)論(0)  編輯  收藏

    Log 問題域

    • 如何不帶來額外的效率損失
    • 如何在程序運(yùn)行出錯(cuò)時(shí)記錄盡可能多的信息
    • 如何方便查找特定條件的錯(cuò)誤
    • 如何橫切的添加通用信息

    如何不帶來額外的效率損失


    在之前接觸的一個(gè)大型產(chǎn)品中見過散布著如下代碼:

    if (Log.Level > DEBUG) {
        logger.write(some_method_to_build_the_log_string());
    }

    問為什么不在logger.write()里面判斷日志級(jí)別, 這樣外面寫起來就很清爽

    logger.write(some_method_to_build_the_log_string());

    答曰效率問題, 后面一種寫法會(huì)導(dǎo)致無論日志最終有沒有被寫入, some_method_to_build_the_log_string()都會(huì)先行被調(diào)用求值, 而這可能很耗時(shí)...

    一個(gè)解決辦法是額外的中間層: 能夠延時(shí)求值的東東, 比如函數(shù)指針, 函數(shù)對(duì)象, 總而言之能夠保存當(dāng)前上下文而在將來某個(gè)時(shí)刻能夠回調(diào)的東西, 諸如 C# 里的 Func<string>

    這樣logger.write()的簽名就從 void write(string info) 變成 void write(Func<string> getInfo);

    帶來的一個(gè)問題是啥時(shí)真正寫入, 一般可以是用戶事務(wù)結(jié)束的時(shí)候. 其實(shí)當(dāng)并發(fā)用戶量大時(shí), 表面上延時(shí)求值可以不阻礙當(dāng)前請(qǐng)求的處理速度, 但當(dāng)求值發(fā)生時(shí), 可能會(huì)阻礙其它請(qǐng)求的處理. 所以Func<string>代替string效率上的優(yōu)勢(shì)并不明顯, 更多的是代碼上的簡(jiǎn)潔

    (Func<string>的另一個(gè)好處是把IO操作推遲了, 當(dāng)時(shí)沒有IO操作,所有IO操作都被推到完成用戶請(qǐng)求之后再進(jìn)行,尤其是如果因?yàn)槠渌蛐枰袻og存到數(shù)據(jù)庫(kù)的時(shí)候. 當(dāng)然不用Func<string>, 直接用string也可以實(shí)現(xiàn)推遲IO操作, 只需要把string都緩存起來, 找個(gè)時(shí)機(jī)再寫出來即可)

    然而Func<string>更大的意義是解決第二個(gè)問題:


    如何在程序運(yùn)行出錯(cuò)時(shí)記錄盡可能多的信息


    通常最終寫到日志里的信息, 都是根據(jù)配置的級(jí)別決定的, 比如配置了日志級(jí)別是INFO, 那么無論出不出錯(cuò), DEBUG級(jí)別的信息都不會(huì)被寫到日志里. 然而現(xiàn)實(shí)情況是, 一旦出錯(cuò), 我們可能需要DEBUG信息來定位問題. 于是我們不得不把日志級(jí)別設(shè)置成DEBUG,然后重新運(yùn)行應(yīng)用,企圖復(fù)現(xiàn). 但運(yùn)行環(huán)境的差異使得復(fù)現(xiàn)像撞大運(yùn), 可遇不可得. 于是在案發(fā)第一現(xiàn)場(chǎng)就記錄所有線索變得極具效率

    對(duì)日志即時(shí)求值和寫入是很難實(shí)現(xiàn)這個(gè)目的的, 而延時(shí)求值, 回調(diào), 這層額外的間接則將其變得輕而易舉.

    我們要做的就是保存所有寫日志的回調(diào), 直到寫入的那一刻, 根據(jù)某種規(guī)則, 從中挑選部分回調(diào)真正去執(zhí)行; 規(guī)則可以是正常情況下根據(jù)日志級(jí)別設(shè)置, 出錯(cuò)的時(shí)候則全部寫入, 等等

    (這里的目的就是避免日志過于簡(jiǎn)略或者繁瑣, 鼓勵(lì)大家多寫日志而不必?fù)?dān)心運(yùn)行時(shí)效率)

    如何方便查找特定條件的錯(cuò)誤


    查找是數(shù)據(jù)庫(kù)的強(qiáng)項(xiàng), 把日志結(jié)構(gòu)化, 存到數(shù)據(jù)庫(kù)里即可. 這會(huì)帶來事務(wù)的問題: 寫日志是否和用戶正常的業(yè)務(wù)放在一個(gè)事務(wù)里?

    如何橫切的添加通用信息


    如果把log建模為一個(gè)對(duì)象, 可以應(yīng)用builder模式, pipeline等, 讓log對(duì)象依次通過一堆builder組成的pipeline, 每個(gè)builder負(fù)責(zé)給log增磚添瓦, 最后出來的就是一個(gè)包含了各種彼此獨(dú)立的信息的對(duì)象

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲第一成年网站视频| 亚洲日本久久一区二区va| 一级做a爰全过程免费视频毛片| 毛片免费在线观看网址| 日韩亚洲国产综合高清| 手机在线免费视频| 亚洲日本成本人观看| 性做久久久久免费看| 青青草97国产精品免费观看| 亚洲色欲久久久久综合网| 中文字幕手机在线免费看电影 | 无码日韩精品一区二区三区免费| 久久亚洲综合色一区二区三区| 丝袜足液精子免费视频| 亚洲激情在线视频| 久久久久久精品免费看SSS | 亚洲精品麻豆av| 中国精品一级毛片免费播放| 亚洲av福利无码无一区二区| 91免费福利精品国产| 中文字幕乱码亚洲精品一区| 四虎影在线永久免费四虎地址8848aa| 青青免费在线视频| 亚洲av综合avav中文| 中字幕视频在线永久在线观看免费 | 亚洲国产一区二区三区| 99久久国产精品免费一区二区| 久久亚洲日韩看片无码| 在线观看免费a∨网站| 无码的免费不卡毛片视频| 色播亚洲视频在线观看| 18禁成年无码免费网站无遮挡| 日韩在线一区二区三区免费视频 | 99精品在线免费观看| 亚洲熟妇无码一区二区三区导航| 亚洲AV无码专区日韩| 2022久久国产精品免费热麻豆| 亚洲大码熟女在线观看| 亚洲精品无码乱码成人| 成全影视免费观看大全二| 国产免费人成视频在线播放播|