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 69 70
use super::*; 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(target_arch = "wasm32")] { #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = console, js_name = log)] fn console_log(s: &str); } console_log(&format!("{} - {}", record.level(), record.args())); } } } 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(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); }