From 90c07e16e183c8e508a4e777f9624e3d22669118 Mon Sep 17 00:00:00 2001 From: TomZz Date: Sun, 14 Jun 2026 14:00:52 +0800 Subject: [PATCH] Fix: change log timestamps and rolling filename suffix from UTC to local time --- Cargo.lock | 13 ++++++++ Cargo.toml | 3 +- src/app/startup.rs | 75 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 82 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 16f017a..edfbda2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -333,6 +333,7 @@ dependencies = [ "sysinfo 0.33.1", "tar", "thiserror 1.0.69", + "time", "tokio", "tracing", "tracing-appender", @@ -4618,6 +4619,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "objc" version = "0.2.7" @@ -7569,7 +7579,9 @@ checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd" dependencies = [ "deranged", "itoa", + "libc", "num-conv", + "num_threads", "powerfmt", "serde_core", "time-core", @@ -7924,6 +7936,7 @@ dependencies = [ "sharded-slab", "smallvec", "thread_local", + "time", "tracing", "tracing-core", "tracing-log", diff --git a/Cargo.toml b/Cargo.toml index 11f7d94..d4e4d78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,7 @@ tar = "0.4" thiserror = "1" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "io-util", "net", "time", "fs"] } tracing = "0.1" -tracing-subscriber = { version = "0.3", features = ["env-filter"] } +tracing-subscriber = { version = "0.3", features = ["env-filter", "local-time", "time"] } uuid = { version = "1", features = ["v4", "serde"] } walkdir = "2" zip = { version = "2", default-features = false, features = ["deflate"] } @@ -42,6 +42,7 @@ image = { version = "0.25.9", default-features = false, features = ["png"] } futures = "0.3.32" notify = "6.1.1" open = "5.1" +time = { version = "0.3.45", features = ["formatting", "local-offset"] } tracing-appender = "0.2.5" [profile.release] diff --git a/src/app/startup.rs b/src/app/startup.rs index 72d3235..a817078 100644 --- a/src/app/startup.rs +++ b/src/app/startup.rs @@ -4,6 +4,69 @@ use gpui_component::Root; use crate::session::config::ConfigStore; use crate::Ashell; +struct LocalMinutelyRoller { + dir: std::path::PathBuf, + prefix: String, + current_minute: u32, + file: Option, +} + +impl LocalMinutelyRoller { + fn new(dir: std::path::PathBuf, prefix: String) -> Self { + Self { dir, prefix, current_minute: 60, file: None } + } + + fn rollover(&mut self, now: chrono::DateTime) -> std::io::Result<()> { + use chrono::Timelike; + let minute = now.minute(); + if self.current_minute != minute || self.file.is_none() { + let filename = format!("{}-{}.log", self.prefix, now.format("%Y-%m-%d-%H-%M")); + let path = self.dir.join(filename); + let file = std::fs::OpenOptions::new() + .create(true) + .append(true) + .open(&path)?; + self.file = Some(file); + self.current_minute = minute; + + // Cleanup old files keeping last 6 + if let Ok(entries) = std::fs::read_dir(&self.dir) { + let mut files: Vec<_> = entries + .filter_map(|e| e.ok()) + .filter(|e| e.file_name().to_string_lossy().starts_with(&self.prefix)) + .collect(); + files.sort_by_key(|e| e.metadata().and_then(|m| m.modified()).unwrap_or(std::time::SystemTime::UNIX_EPOCH)); + if files.len() > 6 { + for file in files.iter().take(files.len() - 6) { + let _ = std::fs::remove_file(file.path()); + } + } + } + } + Ok(()) + } +} + +impl std::io::Write for LocalMinutelyRoller { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + let now = chrono::Local::now(); + let _ = self.rollover(now); + if let Some(f) = &mut self.file { + f.write(buf) + } else { + Ok(buf.len()) + } + } + + fn flush(&mut self) -> std::io::Result<()> { + if let Some(f) = &mut self.file { + f.flush() + } else { + Ok(()) + } + } +} + pub(crate) fn init_logging() { use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; @@ -13,14 +76,9 @@ pub(crate) fn init_logging() { std::fs::create_dir_all(&log_dir).ok(); - let file_appender = tracing_appender::rolling::Builder::new() - .rotation(tracing_appender::rolling::Rotation::MINUTELY) - .max_log_files(6) - .filename_prefix("ashell.log") - .build(log_dir) - .expect("failed to initialize rolling file appender"); + let roller = LocalMinutelyRoller::new(log_dir.clone(), "ashell".to_string()); - let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender); + let (non_blocking, _guard) = tracing_appender::non_blocking(roller); // Leak the guard so it lives for the entire duration of the app since GPUI's run might not return std::mem::forget(_guard); @@ -28,12 +86,13 @@ pub(crate) fn init_logging() { .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")); let stdout_layer = if cfg!(debug_assertions) { - Some(tracing_subscriber::fmt::layer().with_target(true)) + Some(tracing_subscriber::fmt::layer().with_timer(tracing_subscriber::fmt::time::LocalTime::rfc_3339()).with_target(true)) } else { None }; let file_layer = tracing_subscriber::fmt::layer() + .with_timer(tracing_subscriber::fmt::time::LocalTime::rfc_3339()) .with_writer(non_blocking) .with_ansi(false) .with_target(true);