use serde::{Deserialize, Serialize};
use serde_variant::to_variant_name;
use tracing_subscriber::EnvFilter;
use crate::{app::Hooks, config};
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub enum LogLevel {
#[serde(rename = "off")]
Off,
#[serde(rename = "trace")]
Trace,
#[serde(rename = "debug")]
Debug,
#[serde(rename = "info")]
#[default]
Info,
#[serde(rename = "warn")]
Warn,
#[serde(rename = "error")]
Error,
}
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub enum Format {
#[serde(rename = "compact")]
#[default]
Compact,
#[serde(rename = "pretty")]
Pretty,
#[serde(rename = "json")]
Json,
}
impl std::fmt::Display for LogLevel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
to_variant_name(self).expect("only enum supported").fmt(f)
}
}
const MODULE_WHITELIST: &[&str] = &["loco_rs", "sea_orm_migration", "tower_http", "sqlx::query"];
pub fn init<H: Hooks>(config: &config::Logger) {
if !config.enable {
return;
}
let filter = EnvFilter::try_from_default_env()
.or_else(|_| {
config.override_filter.as_ref().map_or_else(
|| {
EnvFilter::try_new(
MODULE_WHITELIST
.iter()
.map(|m| format!("{}={}", m, config.level))
.chain(std::iter::once(format!(
"{}={}",
H::app_name(),
config.level
)))
.collect::<Vec<_>>()
.join(","),
)
},
EnvFilter::try_new,
)
})
.expect("logger initialization failed");
let builder = tracing_subscriber::FmtSubscriber::builder().with_env_filter(filter);
match config.format {
Format::Compact => builder.compact().init(),
Format::Pretty => builder.pretty().init(),
Format::Json => builder.json().init(),
};
}