Fix: change log timestamps and rolling filename suffix from UTC to local time

This commit is contained in:
TomZz
2026-06-14 14:06:57 +08:00
parent 33a3d624b7
commit 90c07e16e1
3 changed files with 82 additions and 9 deletions
Generated
+13
View File
@@ -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",
+2 -1
View File
@@ -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]
+67 -8
View File
@@ -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<std::fs::File>,
}
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<chrono::Local>) -> 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<usize> {
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);