Fabric 1.0原始碼分析(14) flogging(Fabric日誌系統)
# Fabric 1.0原始碼筆記 之 flogging(Fabric日誌系統)
## 1、flogging概述
flogging,即fabric logging,對第三方日誌包go-logging做了封裝,供全域性使用。go-logging地址:https://github.com/op/go-logging。
flogging程式碼集中在common/flogging目錄下,包括logging.go和grpclogger.go。
* logging.go,定義了預設的日誌格式、日誌級別和日誌輸出,以及modules和peerStartModules做模組和日誌級別的對映。並定義了若干對go-logging封裝的函式。
* grpclogger.go,基於封裝go-logging定義了結構體grpclogger及其方法,並用於設定grpclog。grpclog預設使用go標準庫日誌包,此舉可使得grpclog也使用go-logging和flogging功能。
## 2、flogging的常量和全域性變數
涉及常量:pkgLogID、defaultFormat和defaultLevel,分別表示僅在flogging包內程式碼使用的go-logging名稱、預設的日誌格式和預設的日誌級別。
涉及全域性變數如下:
```go
var (
logger *logging.Logger //僅在flogging包內程式碼使用的logging.Logger物件
defaultOutput *os.File //預設的日誌輸出
modules map[string]string //儲存所有模組及其各自的日誌級別的對映
peerStartModules map[string]string //儲存內容與modules相同
lock sync.RWMutex //RWMutex讀寫鎖
once sync.Once //對於從全域性的角度只需要執行一次的程式碼,比如全域性初化操始作,go語言提供了一個Once型別來保證全域性的唯一性操作
)
//程式碼在common/flogging/logging.go
```
## 3、flogging對go-logging的封裝
### 3.1、flogging包初始化
flogging包初始化,即init()函式,程式碼如下:
```go
func init() {
logger = logging.MustGetLogger(pkgLogID) //建立僅在flogging包內程式碼使用的logging.Logger物件
Reset() //全域性變數初始化為預設值
initgrpclogger() //初始化gRPC Logger,即建立logging.Logger物件,並用這個物件設定grpclog
}
//程式碼在common/flogging/logging.go
```
其中func Reset()程式碼如下。
其作用為:初始化modules和lock,建立一個日誌輸出物件並設定為預設的日誌格式和預設的日誌級別。
設定各模組的日誌級別,並更新modules。
```go
func Reset() {
modules = make(map[string]string) //初始化modules
lock = sync.RWMutex{} //初始化lock
defaultOutput = os.Stderr //預設的日誌輸出置為os.Stderr
//SetFormat()設定並獲取go-logging日誌格式,InitBackend()建立一個日誌輸出物件並設定輸出格式和日誌級別
InitBackend(SetFormat(defaultFormat), defaultOutput)
InitFromSpec("") //設定各模組日誌級別,並更新modules
}
//程式碼在common/flogging/logging.go
```
func InitBackend(formatter logging.Formatter, output io.Writer)程式碼如下。
建立一個日誌輸出物件並設定輸出格式和日誌級別。
```go
func InitBackend(formatter logging.Formatter, output io.Writer) {
backend := logging.NewLogBackend(output, "", 0) //建立一個日誌輸出物件
backendFormatter := logging.NewBackendFormatter(backend, formatter) //設定日誌輸出物件的輸出格式
logging.SetBackend(backendFormatter).SetLevel(defaultLevel, "") //設定日誌輸出物件的日誌級別
}
//程式碼在common/flogging/logging.go
```
func InitFromSpec(spec string) string程式碼如下。
其中spec格式為:[<module>[,<module>...]=]<level>[:[<module>[,<module>...]=]<level>...]。
此處傳入spec為"",將""模組日誌級別設定為defaultLevel,並會將modules初始化為defaultLevel。
```go
levelAll := defaultLevel //defaultLevel為logging.INFO
var err error
if spec != "" { //如果spec不為空,則按既定格式讀取
fields := strings.Split(spec, ":") //按:分割
for _, field := range fields {
split := strings.Split(field, "=") //按=分割
switch len(split) {
case 1: //只有level
if levelAll, err = logging.LogLevel(field); err != nil { //levelAll賦值為logging.LogLevel列舉中定義的Level級別
levelAll = defaultLevel // 如果沒有定義,則使用預設日誌級別
}
case 2: //針對module,module...=level,split[0]為模組集,split[1]為要設定的日誌級別
levelSingle, err := logging.LogLevel(split[1]) //levelSingle賦值為logging.LogLevel列舉中定義的Level級別
modules := strings.Split(split[0], ",") //按,分割獲取模組名
for _, module := range modules {
logging.SetLevel(levelSingle, module) //本條規則中所有模組日誌級別均設定為levelSingle
}
default:
//...
}
}
}
logging.SetLevel(levelAll, "") // 將""模組日誌級別設定為levelAll,如果logging.GetLevel(module)沒找到時將使用""模組日誌級別
for k := range modules {
MustGetLogger(k) //獲取模組日誌級別,並更新modules
}
MustGetLogger(pkgLogID) //pkgLogID及其日誌級別,更新至modules
return levelAll.String() //返回levelAll
//程式碼在common/flogging/logging.go
```
MustGetLogger會調取go-logging包中GetLevel(),附GetLevel()程式碼如下。
優先按module獲取日誌級別,如未找到則按""模組獲取日誌級別,如仍未找到則預設按DEBUG級別。
```go
func (l *moduleLeveled) GetLevel(module string) Level {
level, exists := l.levels[module]
if exists == false {
level, exists = l.levels[""]
if exists == false {
level = DEBUG
}
}
return level
}
//程式碼在github.com/op/go-logging/level.go
```
### 3.2、flogging包封裝的方法
flogging包封裝的方法,如下:
```go
func Reset() //全域性變數初始化為預設值
func SetFormat(formatSpec string) logging.Formatter //設定並獲取go-logging日誌格式
func InitBackend(formatter logging.Formatter, output io.Writer) //建立一個日誌輸出物件並設定輸出格式和日誌級別
func DefaultLevel() string //獲取defaultLevel
func GetModuleLevel(module string) string //呼叫logging.GetLevel(module)獲取模組日誌級別
func SetModuleLevel(moduleRegExp string, level string) (string, error) //包裝setModuleLevel
func setModuleLevel(moduleRegExp string, level string, isRegExp bool, revert bool) (string, error) //設定模組日誌級別並更新modules
func MustGetLogger(module string) *logging.Logger //建立logging.Logger例項,獲取模組日誌級別,並更新modules
func InitFromSpec(spec string) string //設定各模組日誌級別,並更新modules
func SetPeerStartupModulesMap() //modules內容複製給peerStartModules
func GetPeerStartupLevel(module string) string //從peerStartModules中獲取模組日誌級別
func RevertToPeerStartupLevels() error //按peerStartModules中內容,設定模組日誌級別並更新modules
//程式碼在common/flogging/logging.go
```
## 4、grpclogger實現
grpclogger結構體定義:
```go
type grpclogger struct {
logger *logging.Logger
}
//程式碼在common/flogging/grpclogger.go
```
grpclogger初始化:
```go
func initgrpclogger() {
glogger := MustGetLogger(GRPCModuleID) //建立logging.Logger物件,獲取模組日誌級別,並更新modules
grpclog.SetLogger(&grpclogger{glogger}) //用建立的logging.Logger物件設定grpclog
}
//程式碼在common/flogging/grpclogger.go
```
其他方法均為對go-logging的包裝,程式碼如下:
```go
func (g *grpclogger) Fatal(args ...interface{}) {
g.logger.Fatal(args...)
}
func (g *grpclogger) Fatalf(format string, args ...interface{}) {
g.logger.Fatalf(format, args...)
}
func (g *grpclogger) Fatalln(args ...interface{}) {
g.logger.Fatal(args...)
}
// NOTE: grpclog does not support leveled logs so for now use DEBUG
func (g *grpclogger) Print(args ...interface{}) {
g.logger.Debug(args...)
}
func (g *grpclogger) Printf(format string, args ...interface{}) {
g.logger.Debugf(format, args...)
}
func (g *grpclogger) Println(args ...interface{}) {
g.logger.Debug(args...)
}
//程式碼在common/flogging/grpclogger.go
```
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
相關文章
- Fabric 1.0原始碼分析(42)scc(系統鏈碼)原始碼
- Fabric 1.0原始碼分析(47)Fabric 1.0.4 go程式碼量統計原始碼Go
- Fabric 1.0原始碼分析(25) Orderer原始碼
- Fabric 1.0原始碼分析(31) Peer原始碼
- Fabric 1.0原始碼分析(40) Proposal(提案)原始碼
- Fabric 1.0原始碼分析(3)Chaincode(鏈碼)原始碼AI
- Fabric 1.0原始碼分析(42)scc(系統鏈碼) #cscc(通道相關)原始碼
- Fabric 1.0原始碼分析(45)gRPC(Fabric中註冊的gRPC Service)原始碼RPC
- Fabric 1.0原始碼分析(18) Ledger(賬本)原始碼
- Fabric 1.0原始碼分析(43) Tx(Transaction 交易)原始碼
- Fabric 1.0原始碼分析(5)Chaincode(鏈碼)體系總結原始碼AI
- Fabric 1.0原始碼分析(13)events(事件服務)原始碼事件
- Fabric 1.0原始碼分析(26)Orderer #ledger(Orderer Ledger)原始碼
- Fabric 1.0原始碼分析(39) policy(背書策略)原始碼
- Fabric 1.0原始碼分析(9)configtx(配置交易)體系介紹原始碼
- Fabric 1.0原始碼分析(10)consenter(共識外掛)原始碼
- Fabric 1.0原始碼分析(15)gossip(流言演算法)原始碼Go演算法
- Fabric 1.0原始碼分析(23)LevelDB(KV資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(44)Tx #RWSet(讀寫集)原始碼
- Fabric 1.0原始碼分析(8)configtx(配置交易) #genesis(系統通道創世區塊)原始碼
- Fabric 1.0原始碼分析(6)configtx(配置交易) #ChannelConfig(通道配置)原始碼
- Fabric 1.0原始碼分析(20) Ledger #idStore(ledgerID資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(29) Orderer #multichain(多鏈支援包)原始碼AI
- Fabric 1.0原始碼分析(30) Orderer #BroadcastServer(Broadcast服務端)原始碼ASTServer服務端
- Fabric 1.0原始碼分析(35)Peer #EndorserServer(Endorser服務端)原始碼Server服務端
- Fabric 1.0原始碼分析(36) Peer #EndorserClient(Endorser客戶端)原始碼client客戶端
- Fabric 1.0原始碼分析(37) Peer #DeliverClient(Deliver客戶端)原始碼client客戶端
- Fabric 1.0原始碼分析(38) Peer #BroadcastClient(Broadcast客戶端)原始碼ASTclient客戶端
- Fabric 1.0原始碼分析(41)putils(protos/utils工具包)原始碼
- Fabric 1.0原始碼分析(2) blockfile(區塊檔案儲存)原始碼BloC
- Fabric 1.0原始碼分析(7)configtx(配置交易) #configtxgen(生成通道配置)原始碼
- Fabric 1.0原始碼分析(19) Ledger #statedb(狀態資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(21)Ledger #historydb(歷史資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(22)Ledger #blkstorage(block檔案儲存)原始碼BloC
- Fabric 1.0原始碼分析(27) Orderer #configupdate(處理通道配置更新)原始碼
- Fabric 1.0原始碼分析(32) Peer #peer node start命令實現原始碼
- Fabric 1.0原始碼分析(28) Orderer #localconfig(Orderer配置檔案定義)原始碼
- Fabric 1.0原始碼分析(4)Chaincode(鏈碼)#platforms(鏈碼語言平臺)原始碼AIPlatform