use embassy_sync::blocking_mutex::{raw::CriticalSectionRawMutex, Mutex}; use esp_println::println; use log::{LevelFilter, Metadata, Record}; use static_cell::StaticCell; // Provides a threadsafe serial logger pub struct RenderbugLogger { lock: Mutex } impl Default for RenderbugLogger { fn default() -> Self { Self { lock: Mutex::new(()) } } } static MAX_LEVEL: LevelFilter = LevelFilter::Debug; static LOGGER: StaticCell = StaticCell::new(); impl RenderbugLogger { pub fn init_logger() { let logger = LOGGER.init(Default::default()); unsafe { log::set_logger_racy(logger).ok(); log::set_max_level_racy(MAX_LEVEL); }; } } impl log::Log for RenderbugLogger { fn enabled(&self, metadata: &Metadata) -> bool { metadata.level() >= MAX_LEVEL } fn flush(&self) {} fn log(&self, record: &Record) { const RESET: &str = "\u{001B}[0m"; const RED: &str = "\u{001B}[31m"; const GREEN: &str = "\u{001B}[32m"; const YELLOW: &str = "\u{001B}[33m"; const BLUE: &str = "\u{001B}[34m"; const CYAN: &str = "\u{001B}[35m"; const GREY: &str = "\u{001B}[38;5;240m"; let color = match record.level() { log::Level::Error => RED, log::Level::Warn => YELLOW, log::Level::Info => GREEN, log::Level::Debug => BLUE, log::Level::Trace => CYAN, }; let filename = record.file().map_or("???", |f| {f}); let prefix = if filename.chars().nth(0).unwrap() == '/' { record.module_path_static().unwrap() } else { filename.split('/').next().unwrap() }; let suffix = filename.split('/').next_back().unwrap(); self.lock.lock(|_| { println!("{color}{}\t{GREY}{prefix}/{suffix}:{}{RESET}\t{}{RESET}", record.level(), record.line().map_or(0, |f| {f}), record.args()); }); } }