7. 日志模块配置

7.1. 日志模块简介

长安链采用Go语言开发,使用Go语言领域最流行的zap包作为日志记录的实现。按长安链整体软件架构设计,日志模块被定义为通用日志记录器放到common包中,长安链日志接口放到protocol包中,以及长安链日志实现模块放在logger包中。而在各个业务模块中记录日志时,只需要使用protocol.Logger接口即可,从而解耦了各个模块对日志包的依赖,便于各个模块的单元测试和模块级测试。下面分别对各个日志包进行介绍:

7.1.1. common/log

在chainmaker.org/chainmaker/common/log包中,对zap进行了封装,增强了日志文件滚动输出和配置简化。如果是common包或者其他基础软件包有记录日志的需求,可以直接使用该log包的LoggerInterface。

7.1.2. protocol.Logger

在长安链整体架构中,将日志的功能定义为如下接口:protocol.Logger

type Logger interface {
	Debug(args ...interface{})
	Debugf(format string, args ...interface{})
	Debugw(msg string, keysAndValues ...interface{})
	Error(args ...interface{})
	Errorf(format string, args ...interface{})
	Errorw(msg string, keysAndValues ...interface{})
	Fatal(args ...interface{})
	Fatalf(format string, args ...interface{})
	Fatalw(msg string, keysAndValues ...interface{})
	Info(args ...interface{})
	Infof(format string, args ...interface{})
	Infow(msg string, keysAndValues ...interface{})
	Panic(args ...interface{})
	Panicf(format string, args ...interface{})
	Panicw(msg string, keysAndValues ...interface{})
	Warn(args ...interface{})
	Warnf(format string, args ...interface{})
	Warnw(msg string, keysAndValues ...interface{})
	DebugDynamic(getStr func() string)
	InfoDynamic(getStr func() string)
}

各个长安链业务模块在代码中需要记录日志时,都引用这个日志接口即可,而不用关心日志记录的实现。

7.1.3. logger的实现

在chainmaker.org/chainmaker/logger项目中基于common/log(zap的封装)提供了protocol.Logger的实例化实现,这也是在实际长安链使用时的实现。另外为了单元测试的方便,系统还提供了:

  • protocol.test.GoLogger 通过系统的log打印日志

  • protocol.test.HoleLogger 不打印日志

  • protocol.test.TestLogger 通过testing对象打印日志

  • protocol.mock.MockLogger 基于gomock的日志接口实现

7.2. 日志配置

在实际长安链的使用中,一般通过独立的log.yml配置文件来配置长安链节点的日志行为。系统启动时通过读取chainmaker.yml中的log/config_file配置获得log.yml的路径,并读取该日志配置内容。

7.2.1. 基本配置

log:
  system:
    log_level_default: INFO       # 默认日志级别,可配:DEBUG,INFO,WARN,ERROR
    file_path: ./log/system.log   # 日志文件路径
    max_age: 365                  # 日志最长保存时间,单位:天
    rotation_time: 1              # 日志滚动时间,单位:小时
    rotation_size: 100            # 日志滚动大小,单位:MB
    log_in_console: true          # 是否展示日志到终端,仅限于调试使用
    show_color: true              # 是否打印颜色日志
    stack_trace_level: ERROR      # 设置 stack trace 日志级别,当日志信息大于等于此级别时将会输出 stack trace, 置空或无效级别将不会打开 stack trace

最简单的情况下,log.yml中只需要配置log/system即可,其中允许的配置属性和说明如下:

配置项 默认值 说明
log_level_default DEBUG 日志记录级别,大于等于这个级别则记录日志
log_levels 指定模块的日志级别
file_path ./default.log 日志记录的文件名
max_age 365 日志最长保存时间,单位:天
rotation_time 6 日志滚动间隔,单位:小时
rotation_size 100 默认的日志滚动大小,单位:MB
log_in_console true 是否向控制台输出日志
log_by_chain false 根据链ID分文件夹记录日志
json_format false 以JSON格式输出日志
show_color true 控制台打印彩色日志
stack_trace_level ERROR 哪种日志级别时打印调用堆栈
kafka 向Kafka输出日志

7.2.2. 按模块配置日志

7.2.2.1. 模块列表

日志中的打印的模块名 配置的模块名 说明
[Access] access 访问控制
[Blockchain] blockchain 主模块
[ChainConf] chainconf 链配置
[Cli] cli 命令行
[Consensus] consensus 共识
[Core] core 核心
[DPoS] dpos DPos共识
[Ledger] ledger 账本
[Monitor] monitor 监控
[Net] net 网络
[Rpc] rpc RPC服务
[Snapshot] snapshot 快照
[Storage] storage 存储
[Sync] sync 同步
[TxFilter] txfilter 交易过滤
[TxPool] txpool 交易池
[Vm] vm 虚拟机

7.2.2.2. 按模块配置不同日志级别

如果日志级别设置为INFO,而特别关注某几个模块的日志,想针对某几个模块的日志记录为DEBUG,则日志配置如下所示:

log:
  system:
    log_level_default: INFO
    log_levels:
      core: DEBUG
      vm: DEBUG
    file_path: ./log/system.log
    ……

7.2.2.3. 按模块配置不同路径、级别等

除system配置外,长安链还支持针对不同的模块进行完全不同的日志配置,包括日志输出路径、日志级别、日志滚动等等,将日志配置的各项配置到log/module/模块名/模块日志配置下。 比如系统默认是INFO级别,而指定交易池的日志配置为DEBUG级别,单独记录在./log/txpool.log文件中,则日志配置如下:

log:
  system:
    log_level_default: DEBUG
    file_path: ./log/system.log
  module:
    txpool:
      log_level_default: INFO
      file_path: ./log/txpool.log
      max_age: 365                  # 日志最长保存时间,单位:天
      rotation_time: 1              # 日志滚动间隔,单位:小时
      rotation_size: 100              # 日志滚动大小,单位:MB
      log_in_console: false         # 是否展示日志到终端,仅限于调试使用
      show_color: false              # 是否打印颜色日志

7.2.3. 多链模式下按ChainId输出

在多子链模式下,默认所有子链的日志都记录到同一个日志文件中,如果希望对不同的子链分别记录到不同的文件夹,则需要开启log_by_chain配置。开启该配置后,系统会根据配置的日志路径,在日志文件夹中根据子链ChainId创建同名的文件夹,然后将对应子链的日志文件记录到文件夹下。比如当前节点有chain1和chain2两个子链,并而日志配置如下:

log:
  system:
    log_level_default: INFO
    file_path: ./log/system.log
    log_by_chain: true

那么系统将会把日志记录到:

  • ./log/chain1/system.log

  • ./log/chain2/system.log

7.2.4. 日志向Kafka输出

在一些以云原生为基础的场景下,可能希望将日志输出到第三方云服务(比如腾讯云日志服务CLS)或者是Kafka中,为此日志模块提供了作为Kafka生产者,将记录日志文件的同时将日志输出到Kafka的能力。

7.2.4.1. Kafka日志配置

Kafka子项的配置如下:

log:
  system:
    log_level_default: INFO
    file_path: ./log/org1/system.log
    kafka:                    # Kafka配置子项
      servers:
        - "kafkaserver:9096"  # Kafka服务器IP端口,可以是多个
      compression: 1          # 是否压缩:0不压缩,1 Gzip,2 snappy,3 LZ4,4 ZSTD
      topic: ""               # 默认Kafka主题
      topic_mapping:          # 指定不同的子链对应不同的主题
        "chain1":"topic1"     # 子链ChainId对应的Kafka主题
        "chain2":"topic2"
      kafka_version: ""       # 指定Kafka版本,空表示不指定版本
      sasl:                   # Kafka安全设置
        enable: true          # 是否启用安全验证
        username: "user1"     # 用户名
        password: "1"         # 密码
        mechanism: PLAIN      # 模式:OAUTHBEARER或者PLAIN
        version: 1            # SASL协议版本

7.3. 日志查看

7.3.1. VM日志查看

此处介绍在智能合约中使用长安链提供的log接口的日志查看方式。

使用 wasmergasmwxvm引擎日志所在位置为:log/system.log。模块为[vm]

使用dockergo引擎日志所在位置为:

  • log/orgid/go/go.log(默认)

  • log/orgid/docker-go/docker-go.log(旧版)

日志格式为:

`date`	[`logLevel`]	[Contract `chainId`#o#`contractName`#`version`#0#99]	`log`

示例如下:

2022-11-22 18:15:19.816	[INFO]	[Contract chainmaker_testnet_chain#o#test_leader5#1.0#0#99]	save key=1669112119