use crate::config::{LogConfig, TelemetryConfig};
#[allow(dead_code)]
pub fn init(config: &LogConfig) {
let profile = crate::config::resolve_profile(&crate::config::OsEnv);
let _ = init_with_telemetry(config, &TelemetryConfig::default(), Some(profile.as_str()))
.unwrap_or_else(|error| panic!("failed to initialize logging: {error}"));
}
pub fn init_with_telemetry(
config: &LogConfig,
telemetry: &TelemetryConfig,
profile: Option<&str>,
) -> Result<crate::telemetry::TelemetryGuard, crate::telemetry::TelemetryInitError> {
crate::telemetry::init(config, telemetry, profile)
}
#[cfg(test)]
fn is_production() -> bool {
std::env::var("AUTUMN_ENV").is_ok_and(|v| v.eq_ignore_ascii_case("production"))
}
#[cfg(test)]
mod tests {
use rusty_fork::rusty_fork_test;
rusty_fork_test! {
#[test]
fn init_succeeds_first_time() {
let config = LogConfig {
level: "debug".to_owned(),
format: LogFormat::Pretty,
};
init(&config);
}
#[test]
fn init_panics_on_second_call() {
let config = LogConfig {
level: "debug".to_owned(),
format: LogFormat::Pretty,
};
init(&config);
let result = std::panic::catch_unwind(|| {
init(&config); });
assert!(result.is_err(), "init did not panic on second call");
let err = result.unwrap_err();
let msg = err.downcast_ref::<&str>().map_or_else(|| err.downcast_ref::<String>().map_or("unknown", |s| s.as_str()), |s| *s);
assert!(msg.contains("failed to initialize logging"), "Unexpected panic message: {msg}");
}
#[test]
fn init_with_json_format_succeeds() {
let config = LogConfig {
level: "debug".to_owned(),
format: LogFormat::Json,
};
init(&config);
}
#[test]
fn init_with_auto_format_succeeds() {
let config = LogConfig {
level: "debug".to_owned(),
format: LogFormat::Auto,
};
init(&config);
}
#[test]
fn init_with_invalid_level_falls_back_without_panic() {
let config = LogConfig {
level: "invalid_level_format_[without_equal]".to_owned(),
format: LogFormat::Pretty,
};
init(&config);
}
}
use super::*;
use crate::config::{LogConfig, LogFormat};
#[test]
fn is_production_false_by_default() {
assert!(!is_production());
}
#[test]
fn auto_format_is_not_json_in_non_production() {
let use_json = match LogFormat::Auto {
LogFormat::Auto => is_production(),
LogFormat::Pretty => false,
LogFormat::Json => true,
};
assert!(!use_json);
}
#[test]
fn pretty_format_is_never_json() {
let use_json = match LogFormat::Pretty {
LogFormat::Auto => is_production(),
LogFormat::Pretty => false,
LogFormat::Json => true,
};
assert!(!use_json);
}
#[test]
fn json_format_is_always_json() {
let use_json = match LogFormat::Json {
LogFormat::Auto => is_production(),
LogFormat::Pretty => false,
LogFormat::Json => true,
};
assert!(use_json);
}
#[test]
fn valid_filter_parses() {
let config = LogConfig {
level: "debug".to_owned(),
format: LogFormat::Auto,
};
let filter = tracing_subscriber::EnvFilter::try_new(&config.level);
assert!(filter.is_ok());
}
#[test]
fn invalid_filter_falls_back() {
let filter = tracing_subscriber::EnvFilter::try_new("not_a_valid_[directive");
assert!(filter.is_err());
}
#[test]
fn test_init_with_telemetry_forwards_to_telemetry_init() {
use crate::config::{TelemetryConfig, TelemetryProtocol};
let log_config = LogConfig {
level: "debug".to_owned(),
format: LogFormat::Pretty,
};
let telemetry_config = TelemetryConfig {
enabled: true,
strict: true, service_name: "test".to_owned(),
service_namespace: None,
service_version: "1.0.0".to_owned(),
environment: "test".to_owned(),
otlp_endpoint: None,
protocol: TelemetryProtocol::Grpc,
};
let result = init_with_telemetry(&log_config, &telemetry_config, None);
assert!(result.is_err());
}
}