区块链教程Fabric1.0源代码分析flogging(Fabric日志系统)兄弟连区块链

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介:

  区块链教程之Fabric1.0源代码分析flogging(Fabric日志系统),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

Fabric 1.0源代码笔记 之 flogging(Fabric日志系统)

1、flogging概述

flogging,即fabric logging,对第三方日志包go-logging做了封装,供全局使用。go-logging地址: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名称、默认的日志格式和默认的日志级别。

涉及全局变量如下:

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()函数,代码如下:

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。

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)代码如下。
创建一个日志输出对象并设置输出格式和日志级别。

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格式为:[[,...]=][:[[,...]=]...]。
此处传入spec为"",将""模块日志级别设置为defaultLevel,并会将modules初始化为defaultLevel。

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级别。

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包封装的方法,如下:

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结构体定义:

type grpclogger struct {
    logger *logging.Logger
}
//代码在common/flogging/grpclogger.go

grpclogger初始化:

func initgrpclogger() {
    glogger := MustGetLogger(GRPCModuleID)  //创建logging.Logger对象,获取模块日志级别,并更新modules
    grpclog.SetLogger(&grpclogger{glogger}) //用创建的logging.Logger对象设置grpclog
}
//代码在common/flogging/grpclogger.go

其他方法均为对go-logging的包装,代码如下:

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
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
5月前
|
存储 数据采集 数据处理
【Flume拓扑揭秘】掌握Flume的四大常用结构,构建强大的日志收集系统!
【8月更文挑战第24天】Apache Flume是一个强大的工具,专为大规模日志数据的收集、聚合及传输设计。其核心架构包括源(Source)、通道(Channel)与接收器(Sink)。Flume支持多样化的拓扑结构以适应不同需求,包括单层、扇入(Fan-in)、扇出(Fan-out)及复杂多层拓扑。单层拓扑简单直观,适用于单一数据流场景;扇入结构集中处理多源头数据;扇出结构则实现数据多目的地分发;复杂多层拓扑提供高度灵活性,适合多层次数据处理。通过灵活配置,Flume能够高效构建各种规模的数据收集系统。
107 0
|
1月前
|
存储 监控 安全
什么是事件日志管理系统?事件日志管理系统有哪些用处?
事件日志管理系统是IT安全的重要工具,用于集中收集、分析和解释来自组织IT基础设施各组件的事件日志,如防火墙、路由器、交换机等,帮助提升网络安全、实现主动威胁检测和促进合规性。系统支持多种日志类型,包括Windows事件日志、Syslog日志和应用程序日志,通过实时监测、告警及可视化分析,为企业提供强大的安全保障。然而,实施过程中也面临数据量大、日志管理和分析复杂等挑战。EventLog Analyzer作为一款高效工具,不仅提供实时监测与告警、可视化分析和报告功能,还支持多种合规性报告,帮助企业克服挑战,提升网络安全水平。
|
2月前
|
存储 Linux Docker
centos系统清理docker日志文件
通过以上方法,可以有效清理和管理CentOS系统中的Docker日志文件,防止日志文件占用过多磁盘空间。选择合适的方法取决于具体的应用场景和需求,可以结合手动清理、logrotate和调整日志驱动等多种方式,确保系统的高效运行。
166 2
|
3月前
|
XML JSON 监控
告别简陋:Java日志系统的最佳实践
【10月更文挑战第19天】 在Java开发中,`System.out.println()` 是最基本的输出方法,但它在实际项目中往往被认为是不专业和不足够的。本文将探讨为什么在现代Java应用中应该避免使用 `System.out.println()`,并介绍几种更先进的日志解决方案。
75 1
|
3月前
|
监控 网络协议 安全
Linux系统日志管理
Linux系统日志管理
65 3
|
3月前
|
监控 应用服务中间件 网络安全
#637481#基于django和neo4j的日志分析系统
#637481#基于django和neo4j的日志分析系统
48 4
|
3月前
|
数据采集 监控 Java
SpringBoot日志全方位超详细手把手教程,零基础可学习 日志如何配置及SLF4J的使用......
本文是关于SpringBoot日志的详细教程,涵盖日志的定义、用途、SLF4J框架的使用、日志级别、持久化、文件分割及格式配置等内容。
230 0
SpringBoot日志全方位超详细手把手教程,零基础可学习 日志如何配置及SLF4J的使用......
|
5月前
|
存储 消息中间件 人工智能
AI大模型独角兽 MiniMax 基于阿里云数据库 SelectDB 版内核 Apache Doris 升级日志系统,PB 数据秒级查询响应
早期 MiniMax 基于 Grafana Loki 构建了日志系统,在资源消耗、写入性能及系统稳定性上都面临巨大的挑战。为此 MiniMax 开始寻找全新的日志系统方案,并基于阿里云数据库 SelectDB 版内核 Apache Doris 升级了日志系统,新系统已接入 MiniMax 内部所有业务线日志数据,数据规模为 PB 级, 整体可用性达到 99.9% 以上,10 亿级日志数据的检索速度可实现秒级响应。
AI大模型独角兽 MiniMax 基于阿里云数据库 SelectDB 版内核 Apache Doris 升级日志系统,PB 数据秒级查询响应
|
5月前
|
缓存 NoSQL Linux
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
149 1
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
|
3月前
|
监控 Linux 测试技术
Linux系统命令与网络,磁盘和日志监控总结
Linux系统命令与网络,磁盘和日志监控总结
75 0

热门文章

最新文章