#![doc(html_root_url = "https://docs.rs/capture-logger/0.1.1")]
use std::cell::RefCell;
use std::collections::VecDeque;
use std::sync::Once;
pub use log::Level;
static INITIALIZED: Once = Once::new();
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Record {
level: Level,
message: String,
}
impl Record {
pub fn level(&self) -> Level {
self.level
}
pub fn message(&self) -> &str {
&self.message
}
}
thread_local! {
static CAPTURED: RefCell<Option<VecDeque<Record>>> = RefCell::new(None);
}
static LOGGER: Logger = Logger;
struct Logger;
impl log::Log for Logger {
fn enabled(&self, _: &log::Metadata) -> bool {
true
}
fn log(&self, record: &log::Record) {
CAPTURED.with(|cap| {
if let Some(queue) = &mut *cap.borrow_mut() {
queue.push_back(Record {
level: record.level(),
message: format!("{}", record.args()),
});
}
});
}
fn flush(&self) {}
}
pub fn begin_capture() {
INITIALIZED.call_once(|| {
log::set_logger(&LOGGER).unwrap();
log::set_max_level(log::LevelFilter::Trace);
});
CAPTURED.with(|cap| {
let queue = &mut *cap.borrow_mut();
if queue.is_none() {
*queue = Some(VecDeque::new());
} else {
panic!("already captured.")
}
});
}
pub fn end_capture() {
CAPTURED.with(|cap| {
*cap.borrow_mut() = None;
});
}
pub fn pop_captured() -> Option<Record> {
CAPTURED.with(|cap| {
if let Some(queue) = &mut *cap.borrow_mut() {
queue.pop_front()
} else {
panic!("not captured.");
}
})
}
#[cfg(test)]
mod tests {
use super::*;
use log::Log;
#[test]
fn test_logger() {
LOGGER.flush(); }
}