diff options
author | Joscha <joscha@plugh.de> | 2022-09-09 22:24:02 +0200 |
---|---|---|
committer | Joscha <joscha@plugh.de> | 2022-09-09 22:25:09 +0200 |
commit | 8eaec4426b99f820d73fa24e9dd1d9eae18ee498 (patch) | |
tree | 196427246e11c115f1d32ee42d4a667b8b210e88 | |
parent | c07941b3746476feec54ae2ec335e6f6744248f5 (diff) |
Log encountered errors on shutdown
-rw-r--r-- | src/logger.rs | 31 | ||||
-rw-r--r-- | src/main.rs | 21 |
2 files changed, 46 insertions, 6 deletions
diff --git a/src/logger.rs b/src/logger.rs index 1e9422c..d44f923 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -67,6 +67,30 @@ impl ChatMsg for LogMsg { } } +/// Prints all error messages when dropped. +pub struct LoggerGuard { + messages: Arc<Mutex<Vec<LogMsg>>>, +} + +impl Drop for LoggerGuard { + fn drop(&mut self) { + let guard = self.messages.lock(); + let mut error_encountered = false; + for msg in &*guard { + if msg.level == Level::Error { + if !error_encountered { + eprintln!(); + eprintln!("The following errors occurred while cove was running:"); + eprintln!(); + } + error_encountered = true; + eprintln!("{}", msg.content); + eprintln!(); + } + } + } +} + #[derive(Debug, Clone)] pub struct Logger { event_tx: mpsc::UnboundedSender<()>, @@ -178,16 +202,19 @@ impl Log for Logger { } impl Logger { - pub fn init(level: Level) -> (Self, mpsc::UnboundedReceiver<()>) { + pub fn init(level: Level) -> (Self, LoggerGuard, mpsc::UnboundedReceiver<()>) { let (event_tx, event_rx) = mpsc::unbounded_channel(); let logger = Self { event_tx, messages: Arc::new(Mutex::new(Vec::new())), }; + let guard = LoggerGuard { + messages: logger.messages.clone(), + }; log::set_boxed_logger(Box::new(logger.clone())).expect("logger already set"); log::set_max_level(level.to_level_filter()); - (logger, event_rx) + (logger, guard, event_rx) } } diff --git a/src/main.rs b/src/main.rs index a9f192b..dbabcec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,6 +32,7 @@ use clap::Parser; use cookie::CookieJar; use directories::{BaseDirs, ProjectDirs}; use log::info; +use tokio::sync::mpsc; use toss::terminal::Terminal; use ui::Ui; use vault::Vault; @@ -117,6 +118,8 @@ fn set_offline(config: &mut Config, args_offline: bool) { #[tokio::main] async fn main() -> anyhow::Result<()> { + let (logger, logger_guard, logger_rx) = Logger::init(log::Level::Debug); + let args = Args::parse(); let dirs = ProjectDirs::from("de", "plugh", "cove").expect("unable to determine directories"); @@ -142,7 +145,7 @@ async fn main() -> anyhow::Result<()> { }; match args.command.unwrap_or_default() { - Command::Run => run(config, &vault, args.measure_widths).await?, + Command::Run => run(logger, logger_rx, config, &vault, args.measure_widths).await?, Command::Export(args) => export::export(&vault.euph(), args).await?, Command::Gc => { println!("Cleaning up and compacting vault"); @@ -157,12 +160,22 @@ async fn main() -> anyhow::Result<()> { vault.close().await; + // Print all logged errors. This should always happen, even if cove panics, + // because the errors may be key in diagnosing what happened. Because of + // this, it is not implemented via a normal function call. + drop(logger_guard); + println!("Goodbye!"); Ok(()) } -async fn run(config: &'static Config, vault: &Vault, measure_widths: bool) -> anyhow::Result<()> { - let (logger, logger_rx) = Logger::init(log::Level::Debug); +async fn run( + logger: Logger, + logger_rx: mpsc::UnboundedReceiver<()>, + config: &'static Config, + vault: &Vault, + measure_widths: bool, +) -> anyhow::Result<()> { info!( "Welcome to {} {}", env!("CARGO_PKG_NAME"), @@ -172,7 +185,7 @@ async fn run(config: &'static Config, vault: &Vault, measure_widths: bool) -> an let mut terminal = Terminal::new()?; terminal.set_measuring(measure_widths); Ui::run(config, &mut terminal, vault.clone(), logger, logger_rx).await?; - drop(terminal); // So the vault can print again + drop(terminal); // So other things can print again Ok(()) } |