From 4619af6d0cf08f9e4e3fbb4e3e59b117205581b5 Mon Sep 17 00:00:00 2001 From: xjd Date: Thu, 13 Jun 2024 10:12:18 +0800 Subject: [PATCH] Support colored logs Add a default logger implementation for log crate. Add a new feature "log". --- Cargo.toml | 2 + README.md | 1 + contracts/Cargo.lock | 1 + contracts/ckb-std-tests/Cargo.toml | 2 +- contracts/ckb-std-tests/src/entry.rs | 17 +++++-- src/lib.rs | 2 + src/log.rs | 66 ++++++++++++++++++++++++++++ 7 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 src/log.rs diff --git a/Cargo.toml b/Cargo.toml index a4254e8..095946b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ libc = [] ckb2023 = [] # work with `target-feature=-a` Cargo flag dummy-atomic = [] +log = ["dep:log", "dummy-atomic"] [build-dependencies] cc = "1.0" @@ -35,6 +36,7 @@ ckb-types = { package = "ckb-gen-types", version = "0.116", default-features = f buddy-alloc = { version = "0.5.0", optional = true } ckb-x64-simulator = { version = "0.8", optional = true } gcd = "2.3.0" +log = { version = "0.4.21", optional = true, default-features = false } [workspace] exclude = ["test"] diff --git a/README.md b/README.md index 0161fbe..53c9994 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ This library contains several modules that help you write CKB contract with Rust * `entry!` macro: defines contract entry point * `default_alloc!` macro: defines global allocator for no-std rust * `dummy_atomic` module: dummy atomic operations +* `log` module: colored log ### Memory allocator Default allocator uses a mixed allocation strategy: diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index 48d0f04..85df2b5 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -63,6 +63,7 @@ dependencies = [ "cc", "ckb-gen-types", "gcd", + "log", ] [[package]] diff --git a/contracts/ckb-std-tests/Cargo.toml b/contracts/ckb-std-tests/Cargo.toml index 6765686..fd571ec 100644 --- a/contracts/ckb-std-tests/Cargo.toml +++ b/contracts/ckb-std-tests/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -ckb-std = { path = "../../", features = [ "dlopen-c", "dummy-atomic" ] } +ckb-std = { path = "../../", features = [ "dlopen-c", "dummy-atomic", "log"] } blake2b-ref = { version = "0.3", default-features = false } bytes = { version = "1.6.0", default-features = false } log = { version = "0.4.17", default-features = false } diff --git a/contracts/ckb-std-tests/src/entry.rs b/contracts/ckb-std-tests/src/entry.rs index 7b3901f..61916e2 100644 --- a/contracts/ckb-std-tests/src/entry.rs +++ b/contracts/ckb-std-tests/src/entry.rs @@ -22,8 +22,6 @@ use ckb_std::{dynamic_loading, dynamic_loading_c_impl}; use core::ffi::c_void; #[cfg(target_arch = "riscv64")] use core::mem::size_of_val; -#[cfg(target_arch = "riscv64")] -use log::{info, warn}; fn new_blake2b() -> Blake2b { const CKB_HASH_PERSONALIZATION: &[u8] = b"ckb-default-hash"; @@ -423,8 +421,8 @@ fn test_atomic() { assert_eq!(v.len(), 4); // The log crate uses atomic operations. - info!("atomic info"); - warn!("atomic warn"); + log::info!("atomic info"); + log::warn!("atomic warn"); } #[cfg(target_arch = "riscv64")] @@ -786,6 +784,16 @@ fn test_atomic2() { assert_eq!(data, 0xFFFFFFFFFFFFFFFE); } +#[cfg(target_arch = "riscv64")] +fn test_log() { + drop(ckb_std::log::init()); + log::trace!("this is trace"); + log::debug!("this is debug"); + log::info!("this is info"); + log::warn!("this is warn"); + log::error!("this is error"); +} + pub fn main() -> Result<(), Error> { test_basic(); test_load_data(); @@ -812,6 +820,7 @@ pub fn main() -> Result<(), Error> { { test_atomic(); test_atomic2(); + test_log(); } Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index f3ec82b..e88dcfc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,3 +38,5 @@ pub mod dynamic_loading_c_impl; pub use buddy_alloc; #[cfg(feature = "dummy-atomic")] pub mod dummy_atomic; +#[cfg(feature = "log")] +pub mod log; diff --git a/src/log.rs b/src/log.rs new file mode 100644 index 0000000..1359fc4 --- /dev/null +++ b/src/log.rs @@ -0,0 +1,66 @@ +extern crate alloc; + +use crate::syscalls; +use alloc::format; +use log::{Level, Metadata, Record}; +use log::{LevelFilter, SetLoggerError}; + +struct SimpleLogger; + +impl log::Log for SimpleLogger { + fn enabled(&self, _metadata: &Metadata) -> bool { + true + } + + fn log(&self, record: &Record) { + let metadata = record.metadata(); + if self.enabled(metadata) { + let level = metadata.level(); + match level { + Level::Error => syscalls::debug(format!( + "[\x1b[31m{}\x1b[0m {}:{}] {}", + record.level(), + record.file().unwrap_or("???"), + record.line().unwrap_or(0), + record.args() + )), + Level::Warn => syscalls::debug(format!( + "[\x1b[33m{}\x1b[0m {}:{}] {}", + record.level(), + record.file().unwrap_or("???"), + record.line().unwrap_or(0), + record.args() + )), + Level::Info => syscalls::debug(format!( + "[\x1b[32m{}\x1b[0m {}:{}] {}", + record.level(), + record.file().unwrap_or("???"), + record.line().unwrap_or(0), + record.args() + )), + Level::Debug => syscalls::debug(format!( + "[\x1b[34m{}\x1b[0m {}:{}] {}", + record.level(), + record.file().unwrap_or("???"), + record.line().unwrap_or(0), + record.args() + )), + Level::Trace => syscalls::debug(format!( + "[\x1b[36m{}\x1b[0m {}:{}] {}", + record.level(), + record.file().unwrap_or("???"), + record.line().unwrap_or(0), + record.args() + )), + } + } + } + + fn flush(&self) {} +} + +static LOGGER: SimpleLogger = SimpleLogger; + +pub fn init() -> Result<(), SetLoggerError> { + log::set_logger(&LOGGER).map(|()| log::set_max_level(LevelFilter::Trace)) +}