improve logger

This commit is contained in:
vms 2020-10-29 14:08:16 +03:00
parent 8c0a029165
commit e4c1c43c42

View File

@ -19,7 +19,7 @@
//! //!
//! # Examples //! # Examples
//! //!
//! This example initializes [`WasmLogger`] if target arch is Wasm and [`simple_logger`] otherwise. //! This example initializes [`WasmLogger`] with setting log level.
//! Macros from crate [`log`] are used as a logging facade. //! Macros from crate [`log`] are used as a logging facade.
//! //!
//! ``` //! ```
@ -28,11 +28,10 @@
//! use simple_logger; //! use simple_logger;
//! //!
//! fn main() { //! fn main() {
//! if cfg!(target_arch = "wasm32") { //! logger::WasmLogger::new()
//! logger::WasmLogger::init_with_level(log::Level::Info).unwrap(); //! .with_log_leve(log::Level::Info)
//! } else { //! .build()
//! simple_logger::init_with_level(log::Level::Info).unwrap(); //! .unwrap();
//! }
//! //!
//! error!("This message will be logged."); //! error!("This message will be logged.");
//! trace!("This message will not be logged."); //! trace!("This message will not be logged.");
@ -40,100 +39,74 @@
//! //!
//! ``` //! ```
//! //!
//! This example provides methods for [`WasmLogger`] initialization only for Wasm target without
//! specifying logger level:
//!
//! ```
//! use fluence::sdk::*;
//! use log::info;
//!
//! /// This method initializes WasmLogger and should be called at the start of the application.
//! #[no_mangle]
//! #[cfg(target_arch = "wasm32")]
//! fn init_logger() {
//! logger::WasmLogger::init().unwrap();
//! info!("If you can see this message that logger was successfully initialized.");
//! }
//!
//! ```
//!
//! [`WasmLogger`]: struct.WasmLogger.html //! [`WasmLogger`]: struct.WasmLogger.html
//! [`log`]: https://docs.rs/log //! [`log`]: https://docs.rs/log
//! [`simple_logger`]: https://docs.rs/simple_logger
//! [`static_lazy`]: https://docs.rs/lazy_static
//! [`lazy_static::initialize()`]: https://docs.rs/lazy_static/1.3.0/lazy_static/fn.initialize.html
//! [`backend app debugging`]: https://fluence.dev/docs/debugging
use std::collections::HashMap; pub type TargetMap = std::collections::HashMap<&'static str, i64>;
/// The Wasm Logger. /// The Wasm Logger.
/// ///
/// This struct implements the [`Log`] trait from the [`log`] crate, which allows it to act as a /// This struct implements the [`Log`] trait from the [`log`] crate, which allows it to act as a
/// logger. /// logger.
/// ///
/// For initialization of WasmLogger as a default logger please see [`init()`] /// Builder pattern is used here for logger initialization. Please be aware that build must be called
/// and [`init_with_level()`] /// to set the logger up.
/// ///
/// [log-crate-url]: https://docs.rs/log/ /// [log-crate-url]: https://docs.rs/log/
/// [`Log`]: https://docs.rs/log/0.4.6/log/trait.Log.html /// [`Log`]: https://docs.rs/log/0.4.11/log/trait.Log.html
/// [`init_with_level()`]: struct.WasmLogger.html#method.init_with_level
/// [`init()`]: struct.WasmLogger.html#method.init
pub struct WasmLogger { pub struct WasmLogger {
level: log::Level, level: log::Level,
target_map: HashMap<&'static str, i64>, target_map: TargetMap,
} }
#[allow(dead_code)] // #[allow(dead_code)]
impl WasmLogger { impl WasmLogger {
/// Initializes the global logger with a [`WasmLogger`] instance, sets /// Initializes the global logger with a [`WasmLogger`] instance with log level set to `Level::Info`.
/// `max_log_level` to a given log level. /// It is a initial method in this builder chain, please note, that logger wouldn't work without
/// /// subsequent build() call.
/// ``` pub fn new() -> Self {
/// # use fluence::sdk::*; Self {
/// # use log::info; level: log::Level::Info,
/// #
/// # fn main() {
/// if cfg!(target_arch = "wasm32") {
/// logger::WasmLogger::init_with_level(log::Level::Error).unwrap();
/// }
/// error!("This message will be logged.");
/// info!("This message will not be logged.");
/// # }
/// ```
pub fn init_with_level(level: log::Level) -> Result<(), log::SetLoggerError> {
let logger = WasmLogger {
level,
target_map: <_>::default(), target_map: <_>::default(),
}; }
log::set_boxed_logger(Box::new(logger))?;
log::set_max_level(level.to_level_filter());
Ok(())
} }
/// Sets mapping between logging targets and numbers /// Set the log level.
/// Used to efficiently enable & disable logs per target on the host pub fn with_log_level(mut self, level: log::Level) -> Self {
pub fn with_target_map(&mut self, map: HashMap<&'static str, i64>) { self.level = level;
self.target_map = map; self
} }
/// Initializes the global logger with a [`WasmLogger`] instance, sets /// Set mapping between logging targets and numbers.
/// `max_log_level` to `Level::Info`. /// Used to efficiently enable & disable logs per target on the host.
pub fn with_target_map(mut self, map: TargetMap) -> Self {
self.map = map;
self
}
/// Build the real logger.
///
/// This method is a last one in this builder chain and MUST be called to set logger up.
/// Returns a error
/// ///
/// ``` /// ```
/// # use fluence::sdk::*; /// # use fluence::logger;
/// # use log::info; /// # use log::info;
/// # /// #
/// # fn main() { /// # fn main() {
/// if cfg!(target_arch = "wasm32") { /// logger::WasmLogger::new()
/// fluence::logger::WasmLogger::init().unwrap(); /// .with_log_level(log::Level::Trace)
/// } /// .with_target_map(<_>::default())
/// /// .build()
/// error!("This message will be logged."); /// .unwrap();
/// trace!("This message will not be logged.");
/// # } /// # }
/// ``` /// ```
pub fn init() -> Result<(), log::SetLoggerError> { pub fn build(self) -> Result<(), log::SetLoggerError> {
WasmLogger::init_with_level(log::Level::Info) let log_level = self.level;
log::set_boxed_logger(Box::new(self))?;
log::set_max_level(log_level.to_level_filter());
Ok(())
} }
} }
@ -150,16 +123,17 @@ impl log::Log for WasmLogger {
} }
let level = record.metadata().level() as i32; let level = record.metadata().level() as i32;
let default_target = 0;
let target = *self let target = *self
.target_map .target_map
.get(record.metadata().target()) .get(record.metadata().target())
.unwrap_or(&0); .unwrap_or(&default_target);
let msg = record.args().to_string(); let msg = record.args().to_string();
log_utf8_string(level, target, msg.as_ptr() as _, msg.len() as _); log_utf8_string(level, target, msg.as_ptr() as _, msg.len() as _);
} }
// in our case flushing is performed by the VM itself // in our case flushing is performed by a host itself
#[inline] #[inline]
fn flush(&self) {} fn flush(&self) {}
} }