1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
use crate::*; struct Logger; static LOGGERS: once_cell::sync::Lazy<Mutex<Vec<Box<dyn log::Log>>>> = once_cell::sync::Lazy::new(|| Mutex::new(Vec::new())); impl log::Log for Logger { fn enabled(&self, metadata: &log::Metadata) -> bool { if metadata.level() > log::max_level() { return false; } match metadata.target().split_terminator(':').next().unwrap() { "ws" => metadata.level() <= log::Level::Error, "mio" => false, _ => true, } } fn log(&self, record: &log::Record) { if self.enabled(record.metadata()) { for logger in LOGGERS.lock().unwrap().iter_mut() { if logger.enabled(record.metadata()) { logger.log(record); } } #[cfg(any(target_arch = "asmjs", target_arch = "wasm32"))] { let msg = format!("{} - {}", record.level(), record.args()); js! { console.log(@{msg}); } } } } fn flush(&self) {} } static LOGGER: Logger = Logger; pub fn init_with_level(level: log::LevelFilter) -> Result<(), log::SetLoggerError> { log::set_logger(&LOGGER)?; std::panic::set_hook(Box::new(|info| { error!("{}", info); error!("{:?}", backtrace::Backtrace::new()); })); log::set_max_level(level); #[cfg(not(any(target_arch = "asmjs", target_arch = "wasm32")))] add_logger(Box::new({ let mut logger = stderrlog::new(); logger.verbosity(4); logger })); Ok(()) } pub fn init() -> Result<(), log::SetLoggerError> { if cfg!(debug_assertions) { init_with_level(log::LevelFilter::Debug) } else { init_with_level(log::LevelFilter::Info) } } pub fn add_logger(logger: Box<dyn log::Log>) { LOGGERS.lock().unwrap().push(logger); }