use parking_lot::Mutex;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LogLevel {
Trace,
Debug,
Info,
Warn,
Error,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LogRecord {
pub level: LogLevel,
pub target: String,
pub message: String,
pub timestamp_ms: u64,
}
pub trait RuntimeLogger: Send + Sync {
fn log(&self, record: LogRecord);
}
#[derive(Debug, Default, Clone, Copy)]
pub struct StdoutLogger;
impl StdoutLogger {
pub fn new() -> Self {
Self
}
}
impl RuntimeLogger for StdoutLogger {
fn log(&self, record: LogRecord) {
let message = appcore_core::redact_text(&record.message);
let target = appcore_core::redact_text_with_limit(&record.target, 128);
println!(
"[{:?}] {} {} {}",
record.level, target, message, record.timestamp_ms
);
}
}
#[derive(Debug, Default)]
pub struct InMemoryLogger {
records: Mutex<Vec<LogRecord>>,
}
impl InMemoryLogger {
pub fn new() -> Self {
Self {
records: Mutex::new(Vec::new()),
}
}
pub fn len(&self) -> usize {
self.records.lock().len()
}
pub fn is_empty(&self) -> bool {
self.records.lock().is_empty()
}
pub fn records(&self) -> Vec<LogRecord> {
self.records.lock().clone()
}
}
impl RuntimeLogger for InMemoryLogger {
fn log(&self, record: LogRecord) {
let mut record = record;
record.message = appcore_core::redact_text(&record.message);
record.target = appcore_core::redact_text_with_limit(&record.target, 128);
self.records.lock().push(record);
}
}
#[cfg(test)]
#[path = "log_tests.rs"]
mod tests;