use crate::cli::{ColorArg, LogFormatArg, LogLevelArg};
use crate::error::{AppError, AppResult};
use std::io::IsTerminal;
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
pub fn init_tracing(
cli_log_level: LogLevelArg,
cli_log_format: LogFormatArg,
cli_color: ColorArg,
quiet: bool,
json: bool,
) -> AppResult<()> {
let filter = if json {
EnvFilter::new("off")
} else if quiet {
EnvFilter::new("error")
} else {
EnvFilter::new(cli_log_level.as_str())
};
let registry = tracing_subscriber::registry().with(filter);
let use_json = matches!(cli_log_format, LogFormatArg::Json);
if use_json {
let layer = fmt::layer()
.json()
.with_writer(std::io::stderr)
.with_target(false)
.with_current_span(false)
.with_ansi(false);
registry
.with(layer)
.try_init()
.map_err(|e| AppError::Internal(format!("tracing init failed: {e}")))?;
} else {
let ansi = match cli_color {
ColorArg::Never => false,
ColorArg::Always => true,
ColorArg::Auto => std::io::stderr().is_terminal(),
};
let layer = fmt::layer()
.with_writer(std::io::stderr)
.with_target(false)
.with_ansi(ansi);
registry
.with(layer)
.try_init()
.map_err(|e| AppError::Internal(format!("tracing init failed: {e}")))?;
}
Ok(())
}
#[cfg(test)]
mod tests {
#[test]
fn the_config_surface_refuses_an_env_filter_directive() {
use crate::cli::ConfigValue;
for accepted in ["error", "warn", "info", "debug", "trace"] {
assert!(
crate::cli::LogLevelArg::from_config_str(accepted).is_ok(),
"`{accepted}` is one of the five and must be accepted"
);
}
for refused in ["some_crate=warn", "events=trace", "lixo==invalido"] {
assert!(
crate::cli::LogLevelArg::from_config_str(refused).is_err(),
"`{refused}` must be refused; if this fails the key gained \
directive support and GAP-2026-122 can be closed"
);
}
}
}