diff --git a/Cargo.lock b/Cargo.lock index d24c6c3..9e43c4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,21 +63,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - [[package]] name = "arboard" version = "3.6.1" @@ -261,18 +246,6 @@ dependencies = [ "libc", ] -[[package]] -name = "chrono" -version = "0.4.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "num-traits", - "windows-link 0.1.3", -] - [[package]] name = "clipboard-win" version = "5.4.1" @@ -842,10 +815,11 @@ name = "gta-tools" version = "0.9.0" dependencies = [ "catppuccin-egui", - "chrono", "eframe", "egui_extras", + "humantime", "image", + "log", "open", "serde", "serde_json", @@ -885,28 +859,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] -name = "iana-time-zone" -version = "0.1.63" +name = "humantime" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core 0.61.2", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "icu_collections" @@ -2652,7 +2608,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9579d0e6970fd5250aa29aba5994052385ff55cf7b28a059e484bb79ea842e42" dependencies = [ "windows-collections", - "windows-core 0.62.0", + "windows-core", "windows-future", "windows-link 0.2.0", "windows-numerics", @@ -2664,20 +2620,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a90dd7a7b86859ec4cdf864658b311545ef19dbcf17a672b52ab7cefe80c336f" dependencies = [ - "windows-core 0.62.0", -] - -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", + "windows-core", ] [[package]] @@ -2689,8 +2632,8 @@ dependencies = [ "windows-implement", "windows-interface", "windows-link 0.2.0", - "windows-result 0.4.0", - "windows-strings 0.5.0", + "windows-result", + "windows-strings", ] [[package]] @@ -2699,7 +2642,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2194dee901458cb79e1148a4e9aac2b164cc95fa431891e7b296ff0b2f1d8a6" dependencies = [ - "windows-core 0.62.0", + "windows-core", "windows-link 0.2.0", "windows-threading", ] @@ -2744,19 +2687,10 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ce3498fe0aba81e62e477408383196b4b0363db5e0c27646f932676283b43d8" dependencies = [ - "windows-core 0.62.0", + "windows-core", "windows-link 0.2.0", ] -[[package]] -name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link 0.1.3", -] - [[package]] name = "windows-result" version = "0.4.0" @@ -2766,15 +2700,6 @@ dependencies = [ "windows-link 0.2.0", ] -[[package]] -name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link 0.1.3", -] - [[package]] name = "windows-strings" version = "0.5.0" diff --git a/Cargo.toml b/Cargo.toml index c258385..1c21f3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,6 @@ description = "A toolset of convenient things for GTA V Online." catppuccin-egui = { version = "5.6.0", default-features = false, features = [ "egui32", ] } -chrono = { version = "0.4.41", default-features = false, features = ["clock"] } eframe = { version = "0.32.2", default-features = false, features = [ "glow", "default_fonts", @@ -19,7 +18,9 @@ egui_extras = { version = "0.32.2", default-features = false, features = [ "image", "svg", ] } +humantime = "2.3.0" image = { version = "0.25.8", default-features = false, features = ["png"] } +log = "0.4.28" open = "5.3.2" serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.143" diff --git a/src/features/empty_session.rs b/src/features/empty_session.rs index 923b3c5..ce4826b 100644 --- a/src/features/empty_session.rs +++ b/src/features/empty_session.rs @@ -1,7 +1,6 @@ use crate::util::{ consts::game::{EXE_ENHANCED, EXE_LEGACY}, countdown::Countdown, - log, system_info::SystemInfo, }; use std::time::{Duration, Instant}; @@ -65,8 +64,7 @@ pub fn activate(game_handle: &mut HANDLE, system_info: &mut SystemInfo) -> Resul match unsafe { OpenProcess(PROCESS_SUSPEND_RESUME, false, pid) } { Ok(handle) => *game_handle = handle, Err(why) => { - let message = format!("failed to suspend game for empty session:\n{why}"); - log::log(log::LogLevel::Error, &message); + log::error!("failed to suspend game for empty session:\n{why}"); return Err(()); } } diff --git a/src/features/force_close.rs b/src/features/force_close.rs index f22ab1a..35318d3 100644 --- a/src/features/force_close.rs +++ b/src/features/force_close.rs @@ -1,6 +1,5 @@ use crate::util::{ consts::game::{EXE_ENHANCED, EXE_LEGACY}, - log, system_info::SystemInfo, }; use std::time::{Duration, Instant}; @@ -62,10 +61,7 @@ fn activate(system_info: &mut SystemInfo) { .filter(|p| p.name() == EXE_ENHANCED || p.name() == EXE_LEGACY) .for_each(|p| { if !p.kill() { - log::log( - log::LogLevel::Error, - "failed to force close game, probably due to access denied", - ); + log::error!("failed to force close game, probably due to access denied"); } }); system_info.refresh(); diff --git a/src/main.rs b/src/main.rs index 88b8f87..e9c69e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,12 +12,16 @@ fn init_storage() { fn panic_hook(panic_info: &std::panic::PanicHookInfo<'_>) { let backtrace = std::backtrace::Backtrace::capture(); - let message = format!("{panic_info}\nstack backtrace:\n{backtrace}\n"); - util::log::log(util::log::LogLevel::Panic, &message); + let mut message = format!("{panic_info}"); + if backtrace.status() == std::backtrace::BacktraceStatus::Captured { + message += &format!("\nstack backtrace:\n{backtrace}"); + } + log::error!("{message}"); } fn main() { init_storage(); + util::logging::Logger::init(log::LevelFilter::Info); std::panic::set_hook(Box::new(panic_hook)); gui::run::run(); } diff --git a/src/util.rs b/src/util.rs index 8459943..a04b640 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,6 +1,6 @@ pub mod consts; pub mod countdown; -pub mod log; +pub mod logging; pub mod persistent_state; pub mod system_info; pub mod win; diff --git a/src/util/log.rs b/src/util/log.rs deleted file mode 100644 index cd1bbdf..0000000 --- a/src/util/log.rs +++ /dev/null @@ -1,20 +0,0 @@ -use crate::util::consts::path; -use std::{fs::File, io::Write}; -use strum::Display; - -#[derive(Clone, Copy, Display)] -pub enum LogLevel { - Error, - Panic, -} - -pub fn log(level: LogLevel, message: &str) { - let mut file = File::options() - .create(true) - .append(true) - .open(path::APP_LOG.as_path()) - .unwrap(); - let timestamp = chrono::Local::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, false); - let message = format!("[{timestamp}] [{level}]\n{message}\n\n"); - file.write_all(message.as_bytes()).unwrap(); -} diff --git a/src/util/logging.rs b/src/util/logging.rs new file mode 100644 index 0000000..6064313 --- /dev/null +++ b/src/util/logging.rs @@ -0,0 +1,64 @@ +use std::{ + fs::File, + io::Write, + sync::{LazyLock, Mutex}, + time::SystemTime, +}; + +pub struct Logger { + file: Mutex, +} + +static LOGGER: LazyLock = LazyLock::new(|| Logger { + file: File::options() + .create(true) + .append(true) + .open(crate::util::consts::path::APP_LOG.as_path()) + .unwrap() + .into(), +}); + +impl log::Log for Logger { + fn enabled(&self, metadata: &log::Metadata) -> bool { + metadata.level() <= log::Level::Info + } + + fn flush(&self) {} + + fn log(&self, record: &log::Record) { + if self.enabled(record.metadata()) { + self.log_to_stderr(record); + self.log_to_file(record); + } + } +} + +impl Logger { + pub fn init(level: log::LevelFilter) { + log::set_logger(&*LOGGER) + .map(|()| log::set_max_level(level)) + .unwrap(); + } + + fn log_to_file(&self, record: &log::Record) { + let mut file = self.file.lock().unwrap(); + write!( + file, + "[{}][{}]\n{}\n\n", + humantime::format_rfc3339_seconds(SystemTime::now()), + record.level(), + record.args() + ) + .unwrap(); + file.flush().unwrap(); + } + + fn log_to_stderr(&self, record: &log::Record) { + eprintln!( + "[{}][{}]\n{}", + humantime::format_rfc3339_seconds(SystemTime::now()), + record.level(), + record.args() + ) + } +}