日誌庫的設計思路

1、基本思路

日誌庫的設計,抓住最核心的一條,就是日誌從產生到到達最終目的地期間的處理流程。 通常而言,爲了設計一個靈活可擴展,可配置的日誌庫,可將日誌庫抽象爲4個部分:記錄器、過濾器、格式化器、輸出器四部分。微信

組成 描述
記錄器 負責產生日誌記錄的原始信息,好比(原始信息,日誌等級,時間,記錄的位置)等信息
過濾器 負責按指定的過濾條件過濾掉咱們不須要的日誌(好比按日誌等級過濾)
格式化器 負責對原始日誌信息按照咱們想要的格式去格式化
輸出器 負責將將要進行記錄的日誌(通常通過過濾器及格式化器的處理後)記錄到日誌目的地(例如:輸出到文件中)

經過將日誌庫分爲4個抽象,使之成了一個較爲靈活可擴展的日誌庫。好比你想實現輸出到文件和輸出到TCP中這兩個功能,你只需分別實現這兩個輸出器的實例便可。數據結構

實現了上面的抽象就基本實現日誌庫的核心功能。在具體實現上,須要設計一個Logger,將上面的抽象組合起來。另外還有一些其餘的工做須要完善,好比讀取日誌配置文件,根據配置文件中的配置條件去構建相應的代碼等等其餘工做。性能

2、一條日誌的生命週期

可能到目前對日誌庫是怎麼工做的還有些模糊,下面以一條日誌的生命週期爲例來講明日誌庫是怎麼工做的:ui

  1. 產生。info!("log information.");
  2. 通過記錄器。記錄器去獲取日誌發生的時間,位置,線程信息等等信息,會有一個數據結構去存儲你須要的信息(例如:msg:"log information.",time:2018-3-20 10:00:00,level:info,location:main.rs:3 lines
  3. 通過過濾器。決定是否記錄(例如,過濾條件設爲info級如下的過濾掉,這裏條日誌信息等級是info,知足條件,繼續。)
  4. 通過格式化器。假設咱們想輸出爲2018-3-22 10:00:00 [info] log information.
  5. 到輸出器。例如輸出到文件中,咱們就將這條信息寫到文件上(File::write(....);,文件中會記錄2018-3-22 10:00:00 [info] log information.).
  6. 假如你還實現了日誌回滾等功能的話,在日誌寫入文件以後,還要判斷是否觸發日誌回滾操做,若是知足了日誌回滾的條件(好比文件Size超過某一大小),則進行日誌回滾操做。
  7. 這條日誌的生命週期結束了。

3、僞代碼實現:

  1. 從配置文件中讀取配置(可經過序列化或其餘方式),生成Config。
  2. LoggerBuilder根據Config去構造Logger。
  3. 由Logger實現日誌庫的核心功能。
//配置
struct Config {
    level:Level,
    ...
}

//Logger建造者
struct LoggerBuilder {
    ...
}

//Logger
struct Logger {
    record:Recorder,
    filter:Filter,
    formater:Formater,
    output:Output,
}
......
複製代碼

4、更多功能細節

上面是日誌庫設計的主幹,可能咱們還須要更多的功能,好比日誌回滾、運行時修改配置等......spa

對於日誌回滾,可抽象爲兩部分,一個是觸發回滾操做的條件,一個是何種具體的回滾操做。好比,咱們但願當文件大小爲1G時就觸發回滾操做,回滾的具體操做是刪除舊的內容重新開始記錄。這裏須要你作的就是實現(觸發條件+具體操做)這兩個抽象。線程

對於運行時修改配置,實質是根據最新的配置從新生成日誌實例,具體實現時可設置一個定時器,定時去讀取新的配置,依據新的配置從新生成日誌實例,再用這個日誌實例記錄日誌......設計

5、後記

是否是設計日誌庫的時候功能越多越好呢?我的認爲不是的,功能越多,抽象越複雜,代碼越臃腫,好比日誌回滾功能的實現,實現過程當中會不可避免的增長了鎖等,形成性能的降低,因此,夠用就好。日誌

各類語言對應的日誌庫已經有不少了,通常都可以知足須要,若是不滿須要,也能夠加以擴展已知足本身的項目須要。code


歡迎關注微信公衆號,感謝支持,共同進步! orm

讓我思考一下
相關文章
相關標籤/搜索