//! Tracing subscriber initialisation. //! //! Terminal (TTY): human-readable format with colors //! Pipeline (non-TTY): JSON output for VictoriaLogs //! Override via `APP_LOG_FORMAT=json|pretty` env var. use crate::msg_json_fmt::MsgJsonFormat; use once_cell::sync::Lazy; use std::io::IsTerminal; use std::str::FromStr; use tracing_subscriber::Layer; use tracing_subscriber::{ fmt::{self, format::FmtSpan}, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, }; /// Global instance identifier, resolved once at startup. /// Priority: `INSTANCE_ID` env var → system hostname → `"unknown"`. pub static INSTANCE_ID: Lazy = Lazy::new(|| { std::env::var("INSTANCE_ID") .ok() .filter(|s| !s.is_empty()) .or_else(|| { hostname::get() .ok() .and_then(|h| h.into_string().ok()) .filter(|s| !s.is_empty()) }) .unwrap_or_else(|| "unknown".to_string()) }); /// Returns the platform-wide instance identifier for this process. pub fn instance_id() -> String { INSTANCE_ID.clone() } /// Determines the log format based on environment and TTY detection. fn use_json() -> bool { match std::env::var("APP_LOG_FORMAT").as_deref() { Ok("json") => true, Ok("pretty") => false, _ => !std::io::stdout().is_terminal(), // TTY → pretty, non-TTY → json } } /// Initialises the global tracing subscriber. /// /// TTY terminals get human-readable output with colors. /// Non-TTY (pipes, container logs) get JSON for log aggregation. /// `APP_LOG_FORMAT=json|pretty` overrides auto-detection. /// `RUST_LOG` env var controls the log level filter. /// /// Pass `defer = true` when OTLP will be initialized afterwards via `init_otlp()`. pub fn init_tracing_subscriber(level: &str, defer: bool) { let env_filter = EnvFilter::try_from_default_env() .or_else(|_| EnvFilter::from_str(level)) .unwrap_or_else(|_| EnvFilter::from_str("info").expect("default log level")); let fmt_layer: Box + Send + Sync> = if use_json() { let mut layer = fmt::layer().event_format(MsgJsonFormat); layer.set_span_events(FmtSpan::CLOSE); <_ as Layer<_>>::boxed(layer) } else { let mut layer = fmt::layer() .with_target(false) .with_level(true) .with_ansi(std::io::stdout().is_terminal()) .pretty(); layer.set_span_events(FmtSpan::CLOSE); <_ as Layer<_>>::boxed(layer) }; let registry = tracing_subscriber::registry() .with(env_filter) .with(fmt_layer); if defer { return; } let _ = registry.try_init(); }