kairoi 0.2.1

Another application-level tracing library
Documentation
use crate::error::SendSyncError;
use crate::format::Write;
use crate::format::{DefaultFormatter, FormatterSet, Writer};
use crate::{Event, GlobalHandlerBuilder, Handler, Log, SpanRef};
use std::cell::RefCell;
use std::collections::VecDeque;
use std::io::stdout;
use std::ops::Deref;
use std::sync::Arc;

pub trait AddConsoleHandler<T> {
    fn console_handler(self) -> T;
}

impl AddConsoleHandler<GlobalHandlerBuilder> for GlobalHandlerBuilder {
    fn console_handler(self) -> Self {
        self.handler(Box::new(ConsoleHandler::new()))
    }
}

pub struct ConsoleHandler {
    log_queue: RefCell<VecDeque<Arc<Log>>>,
    cursor_saved: RefCell<bool>,
    formatter: Box<dyn FormatterSet>,
}

impl ConsoleHandler {
    pub fn new() -> Self {
        Self {
            log_queue: RefCell::new(VecDeque::new()),
            cursor_saved: RefCell::new(false),
            formatter: Box::new(DefaultFormatter::new()),
        }
    }
}

impl ConsoleHandler {
    fn print(
        &self,
        writer: &mut Writer,
        span: &SpanRef,
        depth: usize,
    ) -> Result<(), SendSyncError> {
        if depth > 0 {
            self.formatter.format(writer, span)?;
        }

        for child in span.children() {
            if let Err(e) = self.print(writer, &child, depth + 1) {
                return Err(e);
            }
        }

        Ok(())
    }
}

impl Handler for ConsoleHandler {
    fn handle(&self, event: &Event) -> Result<(), SendSyncError> {
        match event {
            Event::Log(log) => self.log_queue.borrow_mut().push_back(log.clone()),
            Event::SpanBegin(_) => {}
            Event::SpanEnd(_) => {}
        }

        Ok(())
    }

    fn tick(&self, root: &SpanRef) -> Result<(), SendSyncError> {
        let mut lock = stdout().lock();

        let mut writer = Writer::Io(&mut lock);

        if *self.cursor_saved.borrow() {
            write!(writer, "\x1b[u\x1b[J")?;
        }

        while let Some(log) = self.log_queue.borrow_mut().pop_front() {
            self.formatter.format(&mut writer, log.deref())?
        }

        {
            write!(writer, "\x1b[s")?;
            self.cursor_saved.replace(true);
            self.print(&mut writer, root, 0)?;
        }

        drop(writer);

        std::io::Write::flush(&mut lock)?;

        Ok(())
    }
}