use crate::plugin::Plugin;
use std::borrow::Cow;
use std::fmt;
use std::sync::{Arc, Mutex};
use ek_event::Event;
pub const EVENT_LOG: &str = "eLog";
pub const EVENT_PLUG_DOWN_PREFIX: &str = "ePlugQDown.";
pub const LOG_LEVEL_INFO: u8 = 20;
pub const LOG_LEVEL_WARN: u8 = 30;
pub const LOG_LEVEL_ERROR: u8 = 40;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LogData {
pub level: u8,
pub source: String,
pub msg: String,
}
impl fmt::Display for LogData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[{}] {}: {}", self.level, self.source, self.msg)
}
}
pub type LogSink = Arc<dyn Fn(&LogData) + Send + Sync>;
fn default_console_sink() -> LogSink {
Arc::new(|d: &LogData| println!("{d}"))
}
pub struct LogPlugin {
sink: Mutex<LogSink>,
}
impl LogPlugin {
pub fn console() -> Self {
Self { sink: Mutex::new(default_console_sink()) }
}
pub fn with_sink(sink: impl Fn(&LogData) + Send + Sync + 'static) -> Self {
Self { sink: Mutex::new(Arc::new(sink)) }
}
pub fn set_sink(&self, sink: LogSink) {
*self.sink.lock().unwrap() = sink;
}
}
impl Plugin for LogPlugin {
fn name(&self) -> &str {
"log"
}
fn routes(&self) -> Vec<Cow<'static, str>> {
vec![Cow::Borrowed(EVENT_LOG)]
}
fn on_mail(&self, event: &Event) {
if let Some(d) = event.data.downcast_ref::<LogData>() {
let sink = self.sink.lock().unwrap().clone();
sink(d);
}
}
}