use std::sync::{Arc, OnceLock, RwLock};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RuntimeLogLevel {
Info,
Warn,
Error,
}
#[derive(Debug, Clone)]
pub struct RuntimeLogEvent {
pub level: RuntimeLogLevel,
pub message: String,
}
pub type RuntimeLogCallback = Arc<dyn Fn(&RuntimeLogEvent) + Send + Sync + 'static>;
static RUNTIME_LOG_CALLBACK: OnceLock<RwLock<Option<RuntimeLogCallback>>> = OnceLock::new();
fn runtime_log_callback() -> &'static RwLock<Option<RuntimeLogCallback>> {
RUNTIME_LOG_CALLBACK.get_or_init(|| RwLock::new(None))
}
pub fn set_log_callback(callback: Option<RuntimeLogCallback>) {
if let Ok(mut guard) = runtime_log_callback().write() {
*guard = callback;
}
}
pub fn emit(level: RuntimeLogLevel, message: impl Into<String>) {
let event = RuntimeLogEvent {
level,
message: message.into(),
};
let callback = runtime_log_callback()
.read()
.ok()
.and_then(|guard| guard.as_ref().cloned());
if let Some(callback) = callback {
callback(&event);
}
}
pub fn info(message: impl Into<String>) {
emit(RuntimeLogLevel::Info, message);
}
pub fn warn(message: impl Into<String>) {
emit(RuntimeLogLevel::Warn, message);
}
pub fn error(message: impl Into<String>) {
emit(RuntimeLogLevel::Error, message);
}