Log encountered errors on shutdown

This commit is contained in:
Joscha 2022-09-09 22:24:02 +02:00
parent c07941b374
commit 8eaec4426b
2 changed files with 46 additions and 6 deletions

View file

@ -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)
}
}

View file

@ -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(())
}