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
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 简介 此项目是一个模拟公民身份信息链的区块链项目 github 地址: https://github.com/ak...
    CrazyWolf_46a9阅读 12,819评论 0 0
  • feisky云计算、虚拟化与Linux技术笔记posts - 1014, comments - 298, trac...
    不排版阅读 9,333评论 0 5
  • 安装fabric 1.4版本 刚开始接触区块链,跟着网上的教程搭建hyperledger fabric ,下载的是...
    花爬满篱笆阅读 5,609评论 3 0
  • 那一句誓约 尘封在遥遥的记忆里 再不曾 提起 尘封的过去 尘封的迷局 厚厚的 尘封在不为人知的心底 徒留 回忆 不...
    因为爱所以执着阅读 1,599评论 0 1
  • 你不要让我难过了,你现在就是我活下去的信念 我怕你跟我在一起了,你又没有那么爱我的话委屈了你,还是不能让你每天都很...
    初心归来阅读 2,707评论 0 0