frame_benchmarking_cli/pallet/
logging.rs1use super::LOG_TARGET;
19use sp_core::{LogLevelFilter, RuntimeInterfaceLogLevel};
20use sp_runtime_interface::{
21 pass_by::{PassAs, PassFatPointerAndRead, ReturnAs},
22 runtime_interface,
23};
24use std::cell::OnceCell;
25
26thread_local! {
27 pub static RUNTIME_LOG: OnceCell<env_filter::Filter> = OnceCell::new();
33}
34
35pub fn init(arg: Option<String>) {
40 let filter_str = arg.unwrap_or_else(|| {
41 if let Ok(env) = std::env::var("RUNTIME_LOG") {
42 env
43 } else {
44 log::max_level().to_string()
45 }
46 });
47
48 let filter = env_filter::Builder::new()
49 .try_parse(&filter_str)
50 .expect("Invalid runtime log filter")
51 .build();
52
53 RUNTIME_LOG.with(|cell| {
54 cell.set(filter).expect("Can be set by host");
55 log::info!(target: LOG_TARGET, "Initialized runtime log filter to '{}'", filter_str);
56 });
57}
58
59#[runtime_interface]
61pub trait Logging {
62 #[allow(dead_code)]
63 fn log(
64 level: PassAs<RuntimeInterfaceLogLevel, u8>,
65 target: PassFatPointerAndRead<&str>,
66 message: PassFatPointerAndRead<&[u8]>,
67 ) {
68 let Ok(message) = core::str::from_utf8(message) else {
69 log::error!(target: LOG_TARGET, "Runtime tried to log invalid UTF-8 data");
70 return;
71 };
72
73 let level = log::Level::from(level);
74 let metadata = log::MetadataBuilder::new().level(level).target(target).build();
75
76 if RUNTIME_LOG.with(|filter| filter.get().expect("Must be set by host").enabled(&metadata))
77 {
78 log::log!(target: target, level, "{}", message);
79 }
80 }
81
82 #[allow(dead_code)]
83 fn max_level() -> ReturnAs<LogLevelFilter, u8> {
84 RUNTIME_LOG
85 .with(|filter| filter.get().expect("Must be set by host").filter())
87 .into()
88 }
89}