use tracing_subscriber::Registry;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{EnvFilter, Layer, fmt};
use super::log_transport::use_pretty_output;
const LOG_LEVEL_ENV_VAR: &str = "GITHUB_MCP_LOG_LEVEL";
pub type BoxedLayer = Box<dyn Layer<Registry> + Send + Sync>;
pub fn resolve_log_level() -> String {
std::env::var(LOG_LEVEL_ENV_VAR).unwrap_or_else(|_| "info".to_string())
}
pub fn init_logging(otel_layer: Option<BoxedLayer>) {
let filter = EnvFilter::try_new(resolve_log_level()).unwrap_or_else(|_| EnvFilter::new("info"));
let fmt_layer: BoxedLayer = if use_pretty_output() {
fmt::layer().pretty().with_writer(std::io::stderr).boxed()
} else {
fmt::layer().json().with_writer(std::io::stderr).boxed()
};
let layers: Vec<BoxedLayer> = std::iter::once(fmt_layer).chain(otel_layer).collect();
tracing_subscriber::registry()
.with(layers)
.with(filter)
.init();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn defaults_to_info_when_env_var_unset() {
unsafe {
std::env::remove_var(LOG_LEVEL_ENV_VAR);
}
assert_eq!(resolve_log_level(), "info");
}
#[test]
fn reads_the_configured_level_from_the_env_var() {
unsafe {
std::env::set_var(LOG_LEVEL_ENV_VAR, "debug");
}
assert_eq!(resolve_log_level(), "debug");
unsafe {
std::env::remove_var(LOG_LEVEL_ENV_VAR);
}
}
}