logging.rs
1 use std::collections::HashSet; 2 3 use tracing_subscriber::Layer; 4 use tracing_subscriber::layer::SubscriberExt; 5 6 use crate::cli::Logger; 7 8 pub fn setup(cli: &crate::cli::Cli) -> LoggingGuards { 9 let mut env_filter = tracing_subscriber::EnvFilter::from_default_env(); 10 let log_level = cli.verbosity; 11 let loggers = cli.logger.iter().flatten().copied().collect::<HashSet<_>>(); 12 13 if let Some(level_filter) = log_level 14 .is_present() 15 .then(|| log_level.tracing_level_filter()) 16 { 17 let directive = tracing_subscriber::filter::Directive::from(level_filter); 18 env_filter = env_filter.add_directive(directive); 19 } 20 21 let (file_writer, guard) = { 22 let tpl = loggers.contains(&Logger::File).then(|| { 23 tracing_appender::non_blocking({ 24 let cwd = std::env::current_dir().expect("to get the current dirtectory"); 25 let pid = std::process::id(); 26 let filepath = cwd.join(format!("distrox-cli.{pid}.log")); 27 28 std::fs::OpenOptions::new() 29 .append(true) 30 .create(true) 31 .create_new(true) 32 .open(filepath) 33 .expect("to open a file for log output") 34 }) 35 }); 36 37 match tpl { 38 Some((writer, guard)) => (Some(writer), Some(guard)), 39 _ => (None, None), 40 } 41 }; 42 43 let filter = format!("{env_filter}"); 44 let subscriber = tracing_subscriber::registry::Registry::default().with( 45 tracing_subscriber::fmt::layer() 46 .with_writer(std::io::stderr) 47 .with_filter(env_filter), 48 ); 49 50 let subscriber = { 51 #[cfg(feature = "tracy")] 52 { 53 subscriber.with( 54 loggers 55 .contains(&Logger::Tracy) 56 .then(tracing_tracy::TracyLayer::default), 57 ) 58 } 59 60 #[cfg(not(feature = "tracy"))] 61 { 62 subscriber 63 } 64 }; 65 66 // This is fucked up, feel free to improve 67 if let Err(e) = match file_writer { 68 None => tracing::subscriber::set_global_default(subscriber), 69 Some(file_writer) => { 70 let subscriber = 71 subscriber.with(tracing_subscriber::fmt::layer().with_writer(file_writer)); 72 tracing::subscriber::set_global_default(subscriber) 73 } 74 } { 75 eprintln!("Failed to set global logging subscriber: {e:?}"); 76 std::process::exit(1) 77 }; 78 79 tracing::info!("Logging setup done with following filter: {filter}"); 80 LoggingGuards { guard } 81 } 82 83 pub struct LoggingGuards { 84 #[expect(unused, reason = "Guard type")] 85 guard: Option<tracing_appender::non_blocking::WorkerGuard>, 86 }