HyperLedgerFabric日誌系統改造(源碼改造)

目前fabric的日誌系統是將所有的日誌輸出定向到stderr,這在生產環境中顯然是不可以接受的,日誌持久化成了一個亟待解決的問題。

本篇文章將從源碼入手,改造fabric的日誌系統,實現日誌的持久化、日誌自動切割等功能。

源碼修改

環境準備

  1. 獲取源碼
go get github.com/hyperledger/fabric
  1. 切換到 1.4.4版本(這裏我本地已經搭建了1.4.4版本的fabric鏈,爲了方便測試,選擇1.4.4版本的源碼進行修改)
git checkout v1.4.4

修改源碼

  1. 要支持日誌自動切割、自動清理,需要用到一個日誌切割框架https://github.com/lestrrat-go/file-rotatelogs

  2. fabric的日誌模塊在common/flogging下

  3. 經過摸索,問題定位到common/flogging/logging.go文件的Apply函數,

func (s *Logging) Apply(c Config) error {
  err := s.SetFormat(c.Format)
	if err != nil {
		return err
	}

	if c.LogSpec == "" {
		c.LogSpec = os.Getenv("FABRIC_LOGGING_SPEC")
	}
	if c.LogSpec == "" {
		c.LogSpec = defaultLevel.String()
	}

	err = s.LoggerLevels.ActivateSpec(c.LogSpec)
	if err != nil {
		return err
	}
	
  // 這行代碼一定執行
	if c.Writer == nil {
		c.Writer = os.Stderr
	}
  s.SetWriter(c.Writer)
	var formatter logging.Formatter
	switch s.Encoding() {
	case JSON, LOGFMT:
		formatter = SetFormat(defaultFormat)
	default:
		formatter = SetFormat(c.Format)
	}
	InitBackend(formatter, c.Writer)
	return nil
}

這個函數接收Config對象,而在common/flogging包的初始化方法中,Config僅僅只是毫無內容對象,所以c.Writer最終指向了os.Stderr。

func init() {
	logging, err := New(Config{})
	if err != nil {
		panic(err)
	}

	Global = logging
	logger = Global.Logger("flogging")
	grpcLogger := Global.ZapLogger("grpc")
	grpclog.SetLogger(NewGRPCLogger(grpcLogger))
}

4.可以修改c.Writer使它指向文件輸出,這裏使用環境變量控制日誌的持久化以及持久化的路徑,完整代碼如下

func (s *Logging) Apply(c Config) error {
	err := s.SetFormat(c.Format)
	if err != nil {
		return err
	}

	if c.LogSpec == "" {
		c.LogSpec = os.Getenv("FABRIC_LOGGING_SPEC")
	}
	if c.LogSpec == "" {
		c.LogSpec = defaultLevel.String()
	}

	err = s.LoggerLevels.ActivateSpec(c.LogSpec)
	if err != nil {
		return err
	}

	if c.Writer == nil {
		c.Writer = os.Stderr
	}
  // 如果開啓了持久化,則持久化到文件,並且使用rotatelogs來管理日誌
	if enable,err:=strconv.ParseBool(os.Getenv("FABRIC_LOG_PERSISTENCE"));err==nil&&enable{
		filePath:=os.Getenv("FABRIC_LOG_PERSISTENCE_PATH")
		if filePath == ""{
      // 持久化路徑未配置的情況下,使用默認路徑
			filePath = "/var/log/hyperledger/fabric/logs"
		}
		fileName := path.Join(filePath,"log")
		logWriter, err := rotatelogs.New(fileName + ".%Y%m%d.log",
			rotatelogs.WithLinkName(fileName),// 軟鏈接
			rotatelogs.WithMaxAge(7*24*time.Hour), //日誌保留7天
			rotatelogs.WithRotationTime(24*time.Hour))// 每天切割一次
		if err!=nil{
			panic("build logWriter failed")
		}
		c.Writer = logWriter
	}
	s.SetWriter(c.Writer)
	var formatter logging.Formatter
	switch s.Encoding() {
	case JSON, LOGFMT:
		formatter = SetFormat(defaultFormat)
	default:
		formatter = SetFormat(c.Format)
	}
	InitBackend(formatter, c.Writer)
	return nil
}

構建鏡像

官方已經寫好了所有鏡像製作過程,在根目錄下執行即可(建議在linux下執行)

make all

執行完後即可以看到製作好的鏡像:

image-20200422192629784

可以想辦法將鏡像保存下來,通過docker save 或者將它推到鏡像倉庫。

運行測試

這裏只需注意設置好環境變量即可

FABRIC_LOG_PERSISTENCE=true
FABRIC_LOG_PERSISTENCE_PATH=/var/run/hyperlerdger/fabric/peer/logs
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章