前言
整理在开发pallet过程中使用到的代码打印控制台。官方资料:https://docs.substrate.io/test/debug/#logging-utilities
主要有以下几种:
创建项目
进入到/substrate-node-template
中,接着进入到目录pallets中,创建我们自己的lfhuang-debug-pallet
。并且将这pallet加载到runtime中。
使用Logging utilities
通过使用 log crate 代码包在代码中使用log
输出日志,包括debug和info等,和Java类似用法。
需要引入的依赖:
[package]
name = "lfhuang-debug-pallet"
description = "FRAME pallet template for debug"
authors = ["lfhuang"]
...
[dependencies]
log = "0.4.17"
...
接着可以在lib.rs
业务代码使用log进行打印。
#[pallet::weight(0)]
pub fn do_something(origin: OriginFor<T>, something: u32) -> DispatchResult {
let who = ensure_signed(origin)?;
<Something<T>>::put(something);
// Debug方式一 log
log::info!(
"🥸 🥸 🥸 ######################## called by something:{:?} and signer:{:?}",
something,
who
);
Self::deposit_event(Event::SomethingStored(something, who));
Ok(())
}
通过调用交易凭证能看到输出日志信息如下:
使用Printable trait
通过使用Printable trait 代码包实现它,下面通过Error类型实现打印输出日志信息。需要开启debug环境变量模式启动。
当前非test调试代码,所以sp-runtime
的相关依赖需要放到[dependencies]
依赖下。
...
[dependencies]
sp-runtime = { version = "7.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" }
...
// 引入依赖
use sp_runtime::print;
use sp_runtime::traits::Printable;
...
#[pallet::error]
pub enum Error<T> {
/// Value was None
NoneValue,
/// Value reached maximum and cannot be incremented further
StorageOverflow,
}
impl<T: Config> Printable for Error<T> {
fn print(&self) {
match self {
Error::NoneValue => "Invalid Value".print(),
Error::StorageOverflow => "Value Exceeded and Overflowed".print(),
_ => "Invalid Error Case".print(),
}
}
}
...
#[pallet::weight(0)]
pub fn cause_error(origin: OriginFor<T>) -> DispatchResult {
// 检查是否已签名
let _who = ensure_signed(origin)?;
print("🥸 🥸 🥸 ########### 错误原因... #############");
match <Something<T>>::get() {
None => {
print(Error::<T>::NoneValue); // Debug方式二,默认是debug级别,所以启动时候把环境变量调整到debug启动
Err(Error::<T>::NoneValue)?
},
Some(old) => {
let new = old.checked_add(1).ok_or({
print(Error::<T>::StorageOverflow);
Error::<T>::StorageOverflow
})?;
<Something<T>>::put(new);
Ok(())
},
}
}
首次调用cause_error
没有值则会报Error::NoneValue
错误,需要调用do_something
方法设置一个值,接着再掉用cause_error
方法则存储值会加1,同时也会报Error::StorageOverflow
错误。
使用print
使用print函数进行调试记录runtime执行状态。需要导入use sp_runtime::print;
和上面的Printable trait方式差不多,输出打印日志都使用到了print();
需要开启debug环境变量模式启动。
官网例子中的print!();
编译报错。部分代码例子如下:
#[pallet::weight(0)]
pub fn do_something(origin: OriginFor<T>, something: u32) -> DispatchResult {
let who = ensure_signed(origin)?; // 检查是否已签名
print("🥸 🥸 🥸 开始设置值..."); // Debug方式三 print,默认是debug级别,所以启动时候把环境变量调整到debug启动
<Something<T>>::put(something);
print("🥸 🥸 🥸 存储值完成...");
// Debug方式一 log
log::info!(
"🥸 🥸 🥸 ######################## called by something:{:?} and signer:{:?}",
something,
who
);
Self::deposit_event(Event::SomethingStored(something, who));
Ok(())
}
使用if_std
使用if_std宏的方式实现调试。
...
[dependencies]
sp-std = { version = "5.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" }
...
// 引入依赖
use sp_std::if_std;
println!
语句应该在if_std
宏的内部。
#[pallet::weight(0)]
pub fn do_something(origin: OriginFor<T>, something: u32) -> DispatchResult {
let who = ensure_signed(origin)?; // 检查是否已签名
print("🥸 🥸 🥸 开始设置值..."); // Debug方式三 print,默认是debug级别,所以启动时候把环境变量调整到debug启动
<Something<T>>::put(something);
print("🥸 🥸 🥸 存储值完成...");
// Debug方式一 log
log::info!(
"🥸 🥸 🥸 ######################## called by something:{:?} and signer:{:?}",
something,
who
);
// Debug方式四 if_std!宏
if_std! {
println!("😂 😂 😂 ################## Hello native world! something value: {}",something);
println!("😂 😂 😂 ################## 调用者的交易账户是: {:#?}", who);
}
Self::deposit_event(Event::SomethingStored(something, who));
Ok(())
}
检查编译代码
cargo check -p node-template-runtime --release
编译节点模板
返回到项目根目录下/substrate-node-template
cargo build --package node-template --release
启动节点
运行一个临时节点,该节点将在流程结束时删除所有配置,指定开发链
./target/release/node-template --tmp --dev
使用RUST_LOG环境变量运行节点二进制文件以打印值。
RUST_LOG=runtime=debug ./target/release/node-template --tmp --dev
连接节点
1、在浏览器中输入https://polkadot.js.org/apps/#/explorer
2、点击左上角会展开
3、在展开的菜单中点击 DEVELOPMENT
4、点击 Local Node
5、点击 switch (转换到本地网络)