use std::sync::Arc;
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum LogLevel {
Trace,
Debug,
Info,
Warn,
Error,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LogRecord {
level: LogLevel,
target: String,
message: String,
}
impl LogRecord {
#[must_use]
pub fn new(level: LogLevel, target: impl Into<String>, message: impl Into<String>) -> Self {
Self {
level,
target: target.into(),
message: message.into(),
}
}
#[must_use]
pub const fn level(&self) -> LogLevel {
self.level
}
#[must_use]
pub fn target(&self) -> &str {
&self.target
}
#[must_use]
pub fn message(&self) -> &str {
&self.message
}
}
pub trait LogSink: Send + Sync {
fn log(&self, record: &LogRecord);
}
#[derive(Debug, Default)]
pub struct NoopLogSink;
impl LogSink for NoopLogSink {
fn log(&self, _record: &LogRecord) {}
}
#[derive(Clone)]
pub struct Logger {
sink: Arc<dyn LogSink>,
}
impl Logger {
#[must_use]
pub fn new(sink: Arc<dyn LogSink>) -> Self {
Self { sink }
}
pub fn emit(&self, record: &LogRecord) {
self.sink.log(record);
}
pub fn log(&self, level: LogLevel, target: impl Into<String>, message: impl Into<String>) {
self.emit(&LogRecord::new(level, target, message));
}
}
impl Default for Logger {
fn default() -> Self {
Self::new(Arc::new(NoopLogSink))
}
}