use std::fmt::Arguments; use std::fs::File; use std::io::Write; use std::rc::Rc; use futures::future::LocalBoxFuture; use hashbrown::HashMap; use orchid_base::{LogWriter, Logger, is}; use crate::{api, notify}; pub(crate) struct LogWriterImpl { category: String, strat: api::LogStrategy, } impl LogWriter for LogWriterImpl { fn write_fmt<'a>(&'a self, fmt: Arguments<'a>) -> LocalBoxFuture<'a, ()> { Box::pin(async move { match &self.strat { api::LogStrategy::Discard => (), api::LogStrategy::Default => notify(api::Log { category: is(&self.category).await.to_api(), message: fmt.to_string() }) .await, api::LogStrategy::File { path, .. } => { let mut file = (File::options().write(true).create(true).truncate(false).open(path)) .unwrap_or_else(|e| panic!("Could not open {path}: {e}")); file.write_fmt(fmt).unwrap_or_else(|e| panic!("Could not write to {path}: {e}")); }, } }) } } #[derive(Clone)] pub(crate) struct LoggerImpl { default: Option, routing: HashMap, } impl LoggerImpl { pub fn from_api(api: &api::Logger) -> Self { Self { default: api.default.clone(), routing: api.routing.iter().map(|(k, v)| (k.clone(), v.clone())).collect(), } } } impl Logger for LoggerImpl { fn writer(&self, category: &str) -> Rc { Rc::new(LogWriterImpl { category: category.to_string(), strat: self.strat(category) }) } fn strat(&self, category: &str) -> orchid_api::LogStrategy { (self.routing.get(category).cloned().or(self.default.clone())) .expect("Unrecognized log category with no default strategy") } }