9. 日志模块配置
9.1. 日志模块简介
长安链采用Go语言开发,使用Go语言领域最流行的zap包作为日志记录的实现。按长安链整体软件架构设计,日志模块被定义为通用日志记录器放到common包中,长安链日志接口放到protocol包中,以及长安链日志实现模块放在logger包中。而在各个业务模块中记录日志时,只需要使用protocol.Logger接口即可,从而解耦了各个模块对日志包的依赖,便于各个模块的单元测试和模块级测试。下面分别对各个日志包进行介绍:
9.1.1. common/log
在chainmaker.org/chainmaker/common/log包中,对zap进行了封装,增强了日志文件滚动输出和配置简化。如果是common包或者其他基础软件包有记录日志的需求,可以直接使用该log包的LoggerInterface。
9.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)
}
各个长安链业务模块在代码中需要记录日志时,都引用这个日志接口即可,而不用关心日志记录的实现。
9.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的日志接口实现
9.2. 日志配置
在实际长安链的使用中,一般通过独立的log.yml配置文件来配置长安链节点的日志行为。系统启动时通过读取chainmaker.yml中的log/config_file配置获得log.yml的路径,并读取该日志配置内容。
9.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输出日志 |
9.2.2. 按模块配置日志
9.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 | 虚拟机 |
9.2.2.2. 按模块配置不同日志级别
如果日志级别设置为INFO,而特别关注某几个模块的日志,想针对某几个模块的日志记录为DEBUG,则日志配置如下所示:
log:
system:
log_level_default: INFO
log_levels:
core: DEBUG
vm: DEBUG
file_path: ./log/system.log
……
9.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 # 是否打印颜色日志
9.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
9.2.4. 日志向Kafka输出
在一些以云原生为基础的场景下,可能希望将日志输出到第三方云服务(比如腾讯云日志服务CLS)或者是Kafka中,为此日志模块提供了作为Kafka生产者,将记录日志文件的同时将日志输出到Kafka的能力。
9.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协议版本
9.3. 日志查看
9.3.1. VM日志查看
此处介绍在智能合约中使用长安链提供的log接口的日志查看方式。
使用 wasmer
、gasm
、wxvm
引擎日志所在位置为: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