diff --git a/Software/MainBoard/rust/src/log/interceptor.rs b/Software/MainBoard/rust/src/log/interceptor.rs new file mode 100644 index 0000000..549138b --- /dev/null +++ b/Software/MainBoard/rust/src/log/interceptor.rs @@ -0,0 +1,65 @@ +use alloc::string::String; +use alloc::vec::Vec; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::blocking_mutex::Mutex as BlockingMutex; +use embassy_sync::mutex::Mutex; +use log::{LevelFilter, Log, Metadata, Record}; + +pub struct InterceptorLogger { + // Async mutex for start/stop capture from async context + async_capture: Mutex, + // Blocking mutex for the actual data to be used in sync log() + sync_capture: BlockingMutex>>>, +} + +impl InterceptorLogger { + pub const fn new() -> Self { + Self { + async_capture: Mutex::new(()), + sync_capture: BlockingMutex::new(core::cell::RefCell::new(None)), + } + } + + pub async fn start_capture(&self) { + let _guard = self.async_capture.lock().await; + self.sync_capture.lock(|capture| { + *capture.borrow_mut() = Some(Vec::new()); + }); + } + + pub async fn stop_capture(&self) -> Option> { + let _guard = self.async_capture.lock().await; + self.sync_capture + .lock(|capture| capture.borrow_mut().take()) + } + + pub fn init(&'static self) { + log::set_logger(self) + .map(|()| log::set_max_level(LevelFilter::Info)) + .unwrap(); + } +} + +impl Log for InterceptorLogger { + fn enabled(&self, metadata: &Metadata) -> bool { + metadata.level() <= log::Level::Info + } + + fn log(&self, record: &Record) { + if self.enabled(record.metadata()) { + let message = alloc::format!("{}", record.args()); + + // Print to serial using esp_println + esp_println::println!("{}: {}", record.level(), message); + + // Capture if active + self.sync_capture.lock(|capture| { + if let Some(ref mut buffer) = *capture.borrow_mut() { + buffer.push(alloc::format!("{}: {}", record.level(), message)); + } + }); + } + } + + fn flush(&self) {} +}