1. 程式人生 > >03.Fabric原始碼解析---日誌系統

03.Fabric原始碼解析---日誌系統

Fabric原始碼解析3——日誌系統

這裡所說的日誌,是指程式執行過程中列印到終端或日誌檔案,記錄程式執行過程的日誌,而非涉及到fabric記錄交易資料,賬本資料一類的交易日誌。其實日誌系統機制對於原始碼研究可以忽略,且相對簡單,但是一方面日誌系統對於程式執行和除錯必不可少,fabric如何形成這個日誌系統可以學習學習,日誌所列印的內容對閱讀原始碼也是一種提示;另一方面不弄清楚這個日誌,在閱讀原始碼的過程中這些到處出現的列印日誌總像圍繞在原始碼上面的蚊子一樣,鬧心。

Fabric的日誌系統主要使用了第三方包go-logging,可在github.com/op/go-logging下載。很少一部分使用了go語言標準庫中的log。在此基礎上fabric自己封裝出來了flogging,這個f,應該代表fabric吧,意思是說這是fabric的logging。程式碼集中在fabric/common/flogging目錄下,供專案全域性使用。

o-logging簡介

簡單點兒,logging其實就是封裝了各種列印格式,包括訊息層級上的,如DEBU、訊息、注意、警告、錯誤,包括訊息顏色上的,如訊息是正常的綠色、錯誤則是醒目的紅色。

基本用法如下:

//建立一個名字為examplename的日誌物件log
var log = logging.MustGetLogger("examplename")
//建立一個日誌輸出格式物件format,也就是用什麼格式輸出
var format = logging.MustStringFormatter(
    `%{color}%{time:15:04:05.000} %{shortfunc} ▶ %{level:.4s} %{id:03x}%{color:reset} %{message}`,
)
//建立一個日誌輸出物件backend,也就是日誌要列印到哪兒,在此是標準錯誤輸出
backend := logging.NewLogBackend(os.Stderr, "", 0)
//將輸出格式與輸出物件繫結
backendFormatter := logging.NewBackendFormatter(backend, format)
//將綁定了格式的輸出物件設定為日誌的輸出物件
//這樣log列印每一句話都會按格式輸出到backendFormatter所代表的物件裡,在此即是標準錯誤輸出
logging.SetBackend(backendFormatter)
//log列印依據Info資訊
log.Info("info")
//log列印一句Error資訊
log.Error("err")

更多詳細的用法,請在go doc或庫中自行學習。

flogging

在flogging目錄下有兩個檔案,grpclogger.go和logging.go。

grpclogger.go用於設定grpc的日誌,因為grpc預設只是用go語言的標準日誌介面,因此將logging封裝成go語言的標準日誌形式的結構type grpclogger struct {logger *logging.Logger},然後通過initgrpclogger()生成物件供grpc使用,從而實現讓grpc也使用flogging的效果。

logging.go檔案中,自帶一個名為flogging的日誌記錄者logger,同時規定了預設的日誌格式,日誌等級,用defaultFormat,defaultLevel常量表示。預設的輸出端defaultOutput,並有用於存放所有fabric模組日誌的級別對映modules map[string]string,從型別上看其儲存的日誌級別都字串化了。最後還有一個存放每個peer啟動之時的日誌級別的對映peerStartModules map[string]string,由在每個peer啟動完成之時呼叫SetPeerStartupModulesMap()初始化,並可通過呼叫RevertToPeerStartupLevels()恢復初始值。

init函式
init()函式通過呼叫Reset()函式等初始化了一系列預設值,如預設的輸出端被設定成標準錯處輸出,預設輸出級別這設定成info級別。最後呼叫initgrpclogger()初始化了grpc的日誌物件。

MustGetLogger函式
在許多各級不同模組的原始碼中,在全域性的開始處都有類似一句這樣的呼叫,如在fabric/peer/main.go中:var logger = flogging.MustGetLogger(“main”)。這就是呼叫MustGetLogger函式生成一個名為指定了名字的日誌物件,用以記錄該模組的日誌,並用安全的方式(用鎖的方式)將該物件記錄日誌的級別備案到modules中。MustGetLogger函式內部依然用的是go-logging庫的相應函式logging.MustGetLogger()生成的日誌物件。

其他函式
在logging.go中的其他函式,基本都是了封裝go-logging庫函式,供fabric全域性使用。如SetModuleLevel函式,呼叫來呼叫去,其實就是封裝了go-logging庫中的logging.SetLevel()函式,以達到符合fabric自己使用要求的目的,可謂萬變不離其宗。