From acaed2533ff4a6a19b00e9a6ed7afec82c3afc41 Mon Sep 17 00:00:00 2001 From: Daniel Rebelo de Oliveira Date: Fri, 23 Aug 2024 00:07:49 +0100 Subject: [PATCH 1/3] some cleanup of imports --- src/args.rs | 2 +- src/cache/tests.rs | 2 +- src/main.rs | 4 ++-- src/restic.rs | 20 +++++++++++--------- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/args.rs b/src/args.rs index 199a17d..99a6d6b 100644 --- a/src/args.rs +++ b/src/args.rs @@ -15,7 +15,7 @@ pub struct Args { } impl Args { - /// Parse arguments from std::env::args_os(), exit on error. + /// Parse arguments from env::args_os(), exit on error. pub fn parse() -> Self { let cli = Cli::parse(); diff --git a/src/cache/tests.rs b/src/cache/tests.rs index b7982e1..6310fa8 100644 --- a/src/cache/tests.rs +++ b/src/cache/tests.rs @@ -39,7 +39,7 @@ impl Drop for Tempfile { impl Tempfile { pub fn new() -> Self { - let mut path = std::env::temp_dir(); + let mut path = env::temp_dir(); path.push(Uuid::new_v4().to_string()); Tempfile(path) } diff --git a/src/main.rs b/src/main.rs index 5ae11ae..607e8e5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use std::{ fs, - io::stderr, + io::{self, stderr}, sync::{ atomic::{AtomicBool, Ordering}, mpsc::{self, RecvTimeoutError}, @@ -498,7 +498,7 @@ fn ui(mut cache: Cache) -> anyhow::Result> { fn render<'a>( terminal: &'a mut Terminal, app: &App, -) -> std::io::Result> { +) -> io::Result> { terminal.draw(|frame| { let area = frame.area(); let buf = frame.buffer_mut(); diff --git a/src/restic.rs b/src/restic.rs index 501cf61..dbfa12e 100644 --- a/src/restic.rs +++ b/src/restic.rs @@ -1,12 +1,14 @@ +use core::str; #[cfg(not(target_os = "windows"))] use std::os::unix::process::CommandExt; use std::{ borrow::Cow, ffi::OsStr, - fmt::{Display, Formatter}, - io::{BufRead, BufReader, Lines, Read}, + fmt::{self, Display, Formatter}, + io::{self, BufRead, BufReader, Lines, Read}, iter::Step, marker::PhantomData, + mem, process::{Child, ChildStdout, Command, ExitStatusError, Stdio}, str::Utf8Error, }; @@ -21,12 +23,12 @@ use thiserror::Error; #[derive(Debug, Error)] #[error("error launching restic process")] -pub struct LaunchError(#[source] pub std::io::Error); +pub struct LaunchError(#[source] pub io::Error); #[derive(Debug, Error)] pub enum RunError { #[error("error doing IO")] - Io(#[from] std::io::Error), + Io(#[from] io::Error), #[error("error reading input as UTF-8")] Utf8(#[from] Utf8Error), #[error("error parsing JSON")] @@ -43,8 +45,8 @@ pub enum ErrorKind { Run(#[from] RunError), } -impl From for ErrorKind { - fn from(value: std::io::Error) -> Self { +impl From for ErrorKind { + fn from(value: io::Error) -> Self { ErrorKind::Run(RunError::Io(value)) } } @@ -75,7 +77,7 @@ pub struct Error { } impl Display for Error { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match &self.stderr { Some(s) => write!(f, "restic error, stderr dump:\n{}", s), None => write!(f, "restic error"), @@ -141,7 +143,7 @@ impl Restic { ) -> Result> + 'static, LaunchError> { fn parse_file(mut v: Value) -> Option { - let mut m = std::mem::take(v.as_object_mut()?); + let mut m = mem::take(v.as_object_mut()?); Some(File { path: Utf8PathBuf::from(m.remove("path")?.as_str()?), size: m.remove("size")?.as_u64()? as usize, @@ -184,7 +186,7 @@ impl Restic { })?; let r_value = try { output.status.exit_ok()?; - serde_json::from_str(std::str::from_utf8(&output.stdout)?)? + serde_json::from_str(str::from_utf8(&output.stdout)?)? }; match r_value { Err(kind) => Err(Error { From 81075c8d1e1dea3684f8288e11c163959bd3feb9 Mon Sep 17 00:00:00 2001 From: Daniel Rebelo de Oliveira Date: Fri, 23 Aug 2024 00:09:46 +0100 Subject: [PATCH 2/3] switch to simplelog and print log file name --- Cargo.lock | 112 ++++++++++++++++++++++++++++++++++++++-------------- Cargo.toml | 6 +-- src/main.rs | 46 ++++++++++++++------- 3 files changed, 118 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 28a30b5..9c1f48e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -390,6 +390,15 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "directories" version = "5.0.1" @@ -445,20 +454,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" -[[package]] -name = "flexi_logger" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cca927478b3747ba47f98af6ba0ac0daea4f12d12f55e9104071b3dc00276310" -dependencies = [ - "chrono", - "glob", - "log", - "nu-ansi-term", - "regex", - "thiserror", -] - [[package]] name = "getrandom" version = "0.2.15" @@ -470,12 +465,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - [[package]] name = "half" version = "2.4.1" @@ -739,13 +728,10 @@ dependencies = [ ] [[package]] -name = "nu-ansi-term" -version = "0.50.1" +name = "num-conv" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" -dependencies = [ - "windows-sys 0.52.0", -] +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" @@ -756,6 +742,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "number_prefix" version = "0.4.0" @@ -849,6 +844,12 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.20" @@ -869,9 +870,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -978,7 +979,6 @@ dependencies = [ "criterion", "crossterm", "directories", - "flexi_logger", "humansize", "indicatif", "log", @@ -990,6 +990,7 @@ dependencies = [ "scopeguard", "serde", "serde_json", + "simplelog", "thiserror", "unicode-segmentation", "uuid", @@ -1167,6 +1168,17 @@ dependencies = [ "libc", ] +[[package]] +name = "simplelog" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16257adbfaef1ee58b1363bdc0664c9b8e1e30aed86049635fb5f147d065a9c0" +dependencies = [ + "log", + "termcolor", + "time", +] + [[package]] name = "smallvec" version = "1.13.2" @@ -1218,6 +1230,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.63" @@ -1238,6 +1259,39 @@ dependencies = [ "syn", ] +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinytemplate" version = "1.2.1" diff --git a/Cargo.toml b/Cargo.toml index e3ccfb8..bc73b4c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,14 +17,14 @@ chrono = { version = "0.4", features = ["serde"] } clap = { version = "4", features = ["derive", "env"] } crossterm = "0.28" directories = "5" -flexi_logger = "0.28" +simplelog = "0.12" humansize = "2" indicatif = "0.17" log = "0.4" rand = "0.8" ratatui = { version = "0.28", features = [ - "unstable-rendered-line-info", - "unstable-widget-ref", + "unstable-rendered-line-info", + "unstable-widget-ref", ] } rpassword = "7.3.1" rusqlite = { version = "0.32", features = ["bundled", "functions", "trace"] } diff --git a/src/main.rs b/src/main.rs index 607e8e5..5c7cb09 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ use std::{ use anyhow::Context; use args::Args; use camino::{Utf8Path, Utf8PathBuf}; +use chrono::Local; use crossterm::{ event::{KeyCode, KeyModifiers}, terminal::{ @@ -22,9 +23,8 @@ use crossterm::{ ExecutableCommand, }; use directories::ProjectDirs; -use flexi_logger::{FileSpec, Logger, WriteMode}; use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; -use log::{error, info, trace}; +use log::{error, info, trace, LevelFilter}; use rand::{seq::SliceRandom, thread_rng}; use ratatui::{ backend::{Backend, CrosstermBackend}, @@ -38,6 +38,7 @@ use redu::{ restic::{self, escape_for_exclude, Restic, Snapshot}, }; use scopeguard::defer; +use simplelog::WriteLogger; use thiserror::Error; use util::snapshot_short_id; @@ -54,21 +55,38 @@ fn main() -> anyhow::Result<()> { let dirs = ProjectDirs::from("eu", "drdo", "redu") .expect("unable to determine project directory"); - let _logger = { - let mut directory = dirs.data_local_dir().to_path_buf(); - directory.push(Utf8Path::new("logs")); + // Initialize the logger + { + fn generate_filename() -> String { + format!("{}.log", Local::now().format("%Y-%m-%dT%H:%M:%S%.f%:z")) + } - eprintln!("Logging to {:#?}", directory); + let mut path = dirs.data_local_dir().to_path_buf(); + path.push(Utf8Path::new("logs")); + fs::create_dir_all(&path)?; + path.push(generate_filename()); + let file = loop { + // Spin until we hit a timestamp that isn't taken yet. + // With the level of precision that we are using this should virtually + // never run more than once. + match fs::OpenOptions::new() + .write(true) + .create_new(true) + .open(&path) + { + Err(err) if err.kind() == io::ErrorKind::AlreadyExists => + path.set_file_name(generate_filename()), + x => break x, + } + }?; - let filespec = - { FileSpec::default().directory(directory).suppress_basename() }; + eprintln!("Logging to {:#?}", path); - Logger::with(args.log_level) - .log_to_file(filespec) - .write_mode(WriteMode::BufferAndFlush) - .format(flexi_logger::with_thread) - .start()? - }; + let config = simplelog::ConfigBuilder::new() + .set_target_level(LevelFilter::Error) + .build(); + WriteLogger::init(args.log_level, config, file)?; + } unsafe { rusqlite::trace::config_log(Some(|code, msg| { From 4a34421f8d839fb59aa8b74db78fe9aed11bfe5a Mon Sep 17 00:00:00 2001 From: Daniel Rebelo de Oliveira Date: Fri, 23 Aug 2024 17:47:11 +0100 Subject: [PATCH 3/3] improve logs --- src/cache/tests.rs | 4 +++- src/main.rs | 11 +++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/cache/tests.rs b/src/cache/tests.rs index 6310fa8..76f30ab 100644 --- a/src/cache/tests.rs +++ b/src/cache/tests.rs @@ -1,4 +1,6 @@ -use std::{cmp::Reverse, convert::Infallible, fs, iter, mem, path::PathBuf}; +use std::{ + cmp::Reverse, convert::Infallible, env, fs, iter, mem, path::PathBuf, +}; use camino::{Utf8Path, Utf8PathBuf}; use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, Utc}; diff --git a/src/main.rs b/src/main.rs index 5c7cb09..9f42c64 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,7 +24,7 @@ use crossterm::{ }; use directories::ProjectDirs; use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; -use log::{error, info, trace, LevelFilter}; +use log::{debug, error, info, trace, LevelFilter}; use rand::{seq::SliceRandom, thread_rng}; use ratatui::{ backend::{Backend, CrosstermBackend}, @@ -38,7 +38,7 @@ use redu::{ restic::{self, escape_for_exclude, Restic, Snapshot}, }; use scopeguard::defer; -use simplelog::WriteLogger; +use simplelog::{ThreadLogMode, WriteLogger}; use thiserror::Error; use util::snapshot_short_id; @@ -84,6 +84,7 @@ fn main() -> anyhow::Result<()> { let config = simplelog::ConfigBuilder::new() .set_target_level(LevelFilter::Error) + .set_thread_mode(ThreadLogMode::Names) .build(); WriteLogger::init(args.log_level, config, file)?; } @@ -310,17 +311,15 @@ fn fetching_thread_body( "snapshot fetched in {}s ({short_id})", start.elapsed().as_secs_f64() ); - trace!("got snapshot, sending ({short_id})"); if should_quit.load(Ordering::SeqCst) { return Ok(()); } let start = Instant::now(); snapshot_sender.send((snapshot.clone(), sizetree)).unwrap(); - info!( + debug!( "waited {}s to send snapshot ({short_id})", start.elapsed().as_secs_f64() ); - trace!("snapshot sent ({short_id})"); } Ok(()) } @@ -350,7 +349,7 @@ fn db_thread_body( // We wait with timeout to poll the should_quit periodically match snapshot_receiver.recv_timeout(should_quit_poll_period) { Ok((snapshot, sizetree)) => { - info!( + debug!( "waited {}s to get snapshot", start.elapsed().as_secs_f64() );