# 日志模块配置 ## 日志模块简介 长安链采用Go语言开发,使用Go语言领域最流行的zap包作为日志记录的实现。按长安链整体软件架构设计,日志模块被定义为通用日志记录器放到common包中,长安链日志接口放到protocol包中,以及长安链日志实现模块放在logger包中。而在各个业务模块中记录日志时,只需要使用protocol.Logger接口即可,从而解耦了各个模块对日志包的依赖,便于各个模块的单元测试和模块级测试。下面分别对各个日志包进行介绍: ### common/log 在chainmaker.org/chainmaker/common/log包中,对zap进行了封装,增强了日志文件滚动输出和配置简化。如果是common包或者其他基础软件包有记录日志的需求,可以直接使用该log包的LoggerInterface。 ### protocol.Logger 在长安链整体架构中,将日志的功能定义为如下接口:protocol.Logger ```go 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) } ``` 各个长安链业务模块在代码中需要记录日志时,都引用这个日志接口即可,而不用关心日志记录的实现。 ### 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的日志接口实现 ## 日志配置 在实际长安链的使用中,一般通过独立的log.yml配置文件来配置长安链节点的日志行为。系统启动时通过读取chainmaker.yml中的log/config_file配置获得log.yml的路径,并读取该日志配置内容。 ### 基本配置 ```yml 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分文件夹记录日志](#log_by_chain) | | json_format | false | 以JSON格式输出日志 | | show_color | true | 控制台打印彩色日志 | | stack_trace_level | ERROR | 哪种日志级别时打印调用堆栈 | | kafka | 空 | [向Kafka输出日志](#kafka) | ### 按模块配置日志 #### 模块列表 | 日志中的打印的模块名 | 配置的模块名 | 说明 | | :------------------- | :----------- | :------- | | [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 | 虚拟机 | #### 按模块配置不同日志级别 如果日志级别设置为INFO,而特别关注某几个模块的日志,想针对某几个模块的日志记录为DEBUG,则日志配置如下所示: ```yml log: system: log_level_default: INFO log_levels: core: DEBUG vm: DEBUG file_path: ./log/system.log …… ``` #### 按模块配置不同路径、级别等 除system配置外,长安链还支持针对不同的模块进行完全不同的日志配置,包括日志输出路径、日志级别、日志滚动等等,将[日志配置](#log_config)的各项配置到log/module/模块名/模块日志配置下。 比如系统默认是INFO级别,而指定交易池的日志配置为DEBUG级别,单独记录在./log/txpool.log文件中,则日志配置如下: ```yml 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 # 是否打印颜色日志 ``` ### 多链模式下按ChainId输出 在多子链模式下,默认所有子链的日志都记录到同一个日志文件中,如果希望对不同的子链分别记录到不同的文件夹,则需要开启log_by_chain配置。开启该配置后,系统会根据配置的日志路径,在日志文件夹中根据子链ChainId创建同名的文件夹,然后将对应子链的日志文件记录到文件夹下。比如当前节点有chain1和chain2两个子链,并而日志配置如下: ```yml log: system: log_level_default: INFO file_path: ./log/system.log log_by_chain: true ``` 那么系统将会把日志记录到: * ./log/chain1/system.log * ./log/chain2/system.log ### 日志向Kafka输出 在一些以云原生为基础的场景下,可能希望将日志输出到第三方云服务(比如腾讯云日志服务CLS)或者是Kafka中,为此日志模块提供了作为Kafka生产者,将记录日志文件的同时将日志输出到Kafka的能力。 #### Kafka日志配置 Kafka子项的配置如下: ```yml 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协议版本 ``` ## 日志查看 ### 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 ```