use std::sync::OnceLock;
use tracing::Level;
use tracing_subscriber::{EnvFilter, fmt::format::FmtSpan};
#[derive(Debug, Clone, Default)]
pub struct RuniqueLog {
subscriber_level: Option<String>,
pub csrf: Option<Level>,
pub exclusive_login: Option<Level>,
pub filter_fn: Option<Level>,
pub roles: Option<Level>,
pub password_init: Option<Level>,
pub session: Option<Level>,
pub db: Option<Level>,
}
impl RuniqueLog {
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn subscriber_level(mut self, level: impl Into<String>) -> Self {
self.subscriber_level = Some(level.into());
self
}
pub fn init_subscriber(&self) {
let default = self.subscriber_level.as_deref().unwrap_or_else(|| {
if crate::utils::env::is_debug() {
"debug"
} else {
"warn"
}
});
let filter =
std::env::var("RUST_LOG").map_or_else(|_| EnvFilter::new(default), EnvFilter::new);
tracing_subscriber::fmt()
.with_env_filter(filter)
.with_span_events(FmtSpan::CLOSE)
.try_init()
.ok();
}
#[must_use]
pub fn csrf(mut self, level: Level) -> Self {
self.csrf = Some(level);
self
}
#[must_use]
pub fn exclusive_login(mut self, level: Level) -> Self {
self.exclusive_login = Some(level);
self
}
#[must_use]
pub fn filter_fn(mut self, level: Level) -> Self {
self.filter_fn = Some(level);
self
}
#[must_use]
pub fn roles(mut self, level: Level) -> Self {
self.roles = Some(level);
self
}
#[must_use]
pub fn password_init(mut self, level: Level) -> Self {
self.password_init = Some(level);
self
}
#[must_use]
pub fn session(mut self, level: Level) -> Self {
self.session = Some(level);
self
}
#[must_use]
pub fn db(mut self, level: Level) -> Self {
self.db = Some(level);
self
}
#[must_use]
pub fn dev(self) -> Self {
if !crate::utils::env::is_debug() {
return self;
}
self.csrf(Level::DEBUG)
.exclusive_login(Level::DEBUG)
.filter_fn(Level::DEBUG)
.roles(Level::DEBUG)
.password_init(Level::DEBUG)
.session(Level::DEBUG)
.db(Level::DEBUG)
}
}
static LOG_CONFIG: OnceLock<RuniqueLog> = OnceLock::new();
pub fn log_init(config: RuniqueLog) {
LOG_CONFIG.set(config).ok();
}
pub fn get_log() -> &'static RuniqueLog {
LOG_CONFIG.get_or_init(RuniqueLog::default)
}
#[macro_export]
macro_rules! runique_log {
($level:expr, $($args:tt)*) => {
match $level {
::tracing::Level::ERROR => ::tracing::error!($($args)*),
::tracing::Level::WARN => ::tracing::warn!($($args)*),
::tracing::Level::INFO => ::tracing::info!($($args)*),
::tracing::Level::DEBUG => ::tracing::debug!($($args)*),
_ => ::tracing::trace!($($args)*),
}
};
}