use std::io::Write;
use std::sync::{Arc, Mutex};
use tracing_subscriber::fmt::MakeWriter;
#[derive(Clone, Debug, Default)]
pub struct CapturedLog {
buffer: Arc<Mutex<Vec<u8>>>,
}
impl CapturedLog {
pub fn contents(&self) -> String {
let buffer = self
.buffer
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
String::from_utf8_lossy(&buffer).into_owned()
}
pub fn capture<T>(&self, operation: impl FnOnce() -> T) -> T {
let subscriber = tracing_subscriber::fmt()
.with_max_level(tracing::Level::TRACE)
.with_ansi(false)
.with_writer(self.clone())
.finish();
tracing::subscriber::with_default(subscriber, operation)
}
}
impl<'writer> MakeWriter<'writer> for CapturedLog {
type Writer = CapturedLogWriter;
fn make_writer(&'writer self) -> Self::Writer {
CapturedLogWriter {
buffer: Arc::clone(&self.buffer),
}
}
}
pub struct CapturedLogWriter {
buffer: Arc<Mutex<Vec<u8>>>,
}
impl Write for CapturedLogWriter {
fn write(&mut self, bytes: &[u8]) -> std::io::Result<usize> {
self.buffer
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.extend_from_slice(bytes);
Ok(bytes.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}