Merge pull request #9 from fluencelabs/improve_logger

Introduce builder pattern for logger initialization
This commit is contained in:
vms 2020-10-29 23:56:06 +03:00 committed by GitHub
commit a6c587db0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 73 deletions

View File

@ -40,10 +40,15 @@ mod result;
pub use call_parameters::CallParameters;
#[cfg(target_arch = "wasm32")]
pub use call_parameters::get_call_parameters;
pub use export_allocator::allocate;
pub use export_allocator::deallocate;
#[cfg(feature = "logger")]
pub use logger::WasmLogger;
#[cfg(feature = "logger")]
pub use logger::TargetMap;
pub use result::get_result_ptr;
pub use result::get_result_size;
pub use result::set_result_ptr;

View File

@ -19,7 +19,7 @@
//!
//! # 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.
//!
//! ```
@ -28,11 +28,10 @@
//! use simple_logger;
//!
//! fn main() {
//! if cfg!(target_arch = "wasm32") {
//! logger::WasmLogger::init_with_level(log::Level::Info).unwrap();
//! } else {
//! simple_logger::init_with_level(log::Level::Info).unwrap();
//! }
//! logger::WasmLogger::new()
//! .with_log_leve(log::Level::Info)
//! .build()
//! .unwrap();
//!
//! error!("This message will 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
//! [`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.
///
/// This struct implements the [`Log`] trait from the [`log`] crate, which allows it to act as a
/// logger.
///
/// For initialization of WasmLogger as a default logger please see [`init()`]
/// and [`init_with_level()`]
/// Builder pattern is used here for logger initialization. Please be aware that build must be called
/// to set the logger up.
///
/// [log-crate-url]: https://docs.rs/log/
/// [`Log`]: https://docs.rs/log/0.4.6/log/trait.Log.html
/// [`init_with_level()`]: struct.WasmLogger.html#method.init_with_level
/// [`init()`]: struct.WasmLogger.html#method.init
/// [`Log`]: https://docs.rs/log/0.4.11/log/trait.Log.html
pub struct WasmLogger {
level: log::Level,
target_map: HashMap<&'static str, i64>,
target_map: TargetMap,
}
#[allow(dead_code)]
// #[allow(dead_code)]
impl WasmLogger {
/// Initializes the global logger with a [`WasmLogger`] instance, sets
/// `max_log_level` to a given log level.
///
/// ```
/// # use fluence::sdk::*;
/// # use log::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,
/// Initializes the global logger with a [`WasmLogger`] instance with log level set to `Level::Info`.
/// It is a initial method in this builder chain, please note, that logger wouldn't work without
/// subsequent build() call.
pub fn new() -> Self {
Self {
level: log::Level::Info,
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
/// Used to efficiently enable & disable logs per target on the host
pub fn with_target_map(&mut self, map: HashMap<&'static str, i64>) {
/// Set the log level.
pub fn with_log_level(mut self, level: log::Level) -> Self {
self.level = level;
self
}
/// Set mapping between logging targets and numbers.
/// Used to efficiently enable & disable logs per target on the host.
pub fn with_target_map(mut self, map: TargetMap) -> Self {
self.target_map = map;
self
}
/// Initializes the global logger with a [`WasmLogger`] instance, sets
/// `max_log_level` to `Level::Info`.
/// 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;
/// #
/// # fn main() {
/// if cfg!(target_arch = "wasm32") {
/// fluence::logger::WasmLogger::init().unwrap();
/// }
///
/// error!("This message will be logged.");
/// trace!("This message will not be logged.");
/// logger::WasmLogger::new()
/// .with_log_level(log::Level::Trace)
/// .with_target_map(<_>::default())
/// .build()
/// .unwrap();
/// # }
/// ```
pub fn init() -> Result<(), log::SetLoggerError> {
WasmLogger::init_with_level(log::Level::Info)
pub fn build(self) -> Result<(), log::SetLoggerError> {
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 default_target = 0;
let target = *self
.target_map
.get(record.metadata().target())
.unwrap_or(&0);
.unwrap_or(&default_target);
let msg = record.args().to_string();
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]
fn flush(&self) {}
}

View File

@ -68,11 +68,15 @@
#![warn(rust_2018_idioms)]
pub use fluence_sdk_macro::fce;
pub use fluence_sdk_main::CallParameters;
#[cfg(target_arch = "wasm32")]
pub use fluence_sdk_main::get_call_parameters;
#[cfg(feature = "logger")]
pub use fluence_sdk_main::WasmLogger;
#[cfg(feature = "logger")]
pub use fluence_sdk_main::TargetMap;
/// These API functions are intended for internal usage in generated code.
/// Normally, you shouldn't use them.