[log] Allow to use local timezone instead of UTC when writing logs (#269)

* Allow to use local timezone instead of UTC timezone when writing log

* Address PR feedback

* Fix cargo clippy

* revert `time` version

---------

Co-authored-by: Fabian-Lars <fabianlars@fabianlars.de>
pull/270/head
ngapham@kobiton.com 2 years ago committed by GitHub
parent 1d52416f70
commit 6d7b985b46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

29
Cargo.lock generated

@ -2631,6 +2631,15 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "num_threads"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "objc" name = "objc"
version = "0.2.7" version = "0.2.7"
@ -3020,7 +3029,7 @@ dependencies = [
"line-wrap", "line-wrap",
"quick-xml", "quick-xml",
"serde", "serde",
"time 0.3.17", "time 0.3.20",
] ]
[[package]] [[package]]
@ -3901,7 +3910,7 @@ dependencies = [
"sqlx-rt", "sqlx-rt",
"stringprep", "stringprep",
"thiserror", "thiserror",
"time 0.3.17", "time 0.3.20",
"tokio-stream", "tokio-stream",
"url", "url",
"webpki-roots", "webpki-roots",
@ -4239,7 +4248,7 @@ dependencies = [
"sha2 0.10.6", "sha2 0.10.6",
"tauri-utils", "tauri-utils",
"thiserror", "thiserror",
"time 0.3.17", "time 0.3.20",
"uuid 1.3.0", "uuid 1.3.0",
"walkdir", "walkdir",
] ]
@ -4337,7 +4346,7 @@ dependencies = [
"serde_json", "serde_json",
"serde_repr", "serde_repr",
"tauri", "tauri",
"time 0.3.17", "time 0.3.20",
] ]
[[package]] [[package]]
@ -4388,7 +4397,7 @@ dependencies = [
"sqlx", "sqlx",
"tauri", "tauri",
"thiserror", "thiserror",
"time 0.3.17", "time 0.3.20",
"tokio", "tokio",
] ]
@ -4614,11 +4623,13 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.17" version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890"
dependencies = [ dependencies = [
"itoa 1.0.5", "itoa 1.0.5",
"libc",
"num_threads",
"serde", "serde",
"time-core", "time-core",
"time-macros", "time-macros",
@ -4632,9 +4643,9 @@ checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
[[package]] [[package]]
name = "time-macros" name = "time-macros"
version = "0.2.6" version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36"
dependencies = [ dependencies = [
"time-core", "time-core",
] ]

@ -17,7 +17,7 @@ serde_repr = "0.1"
byte-unit = "4.0" byte-unit = "4.0"
fern = "0.6" fern = "0.6"
log = { workspace = true, features = ["kv_unstable"] } log = { workspace = true, features = ["kv_unstable"] }
time = { version = "0.3", features = ["formatting"] } time = { version = "0.3", features = ["formatting", "local-offset"] }
[features] [features]
colored = ["fern/colored"] colored = ["fern/colored"]

@ -21,9 +21,11 @@ use tauri::{
}; };
pub use fern; pub use fern;
use time::OffsetDateTime;
const DEFAULT_MAX_FILE_SIZE: u128 = 40000; const DEFAULT_MAX_FILE_SIZE: u128 = 40000;
const DEFAULT_ROTATION_STRATEGY: RotationStrategy = RotationStrategy::KeepOne; const DEFAULT_ROTATION_STRATEGY: RotationStrategy = RotationStrategy::KeepOne;
const DEFAULT_TIMEZONE_STRATEGY: TimezoneStrategy = TimezoneStrategy::UseUtc;
const DEFAULT_LOG_TARGETS: [LogTarget; 2] = [LogTarget::Stdout, LogTarget::LogDir]; const DEFAULT_LOG_TARGETS: [LogTarget; 2] = [LogTarget::Stdout, LogTarget::LogDir];
/// An enum representing the available verbosity levels of the logger. /// An enum representing the available verbosity levels of the logger.
@ -83,6 +85,23 @@ pub enum RotationStrategy {
KeepOne, KeepOne,
} }
#[derive(Debug, Clone)]
pub enum TimezoneStrategy {
UseUtc,
UseLocal,
}
impl TimezoneStrategy {
pub fn get_now(&self) -> OffsetDateTime {
match self {
TimezoneStrategy::UseUtc => OffsetDateTime::now_utc(),
TimezoneStrategy::UseLocal => {
OffsetDateTime::now_local().unwrap_or_else(|_| OffsetDateTime::now_utc())
} // Fallback to UTC since Rust cannot determine local timezone
}
}
}
#[derive(Debug, Serialize, Clone)] #[derive(Debug, Serialize, Clone)]
struct RecordPayload { struct RecordPayload {
message: String, message: String,
@ -145,6 +164,7 @@ fn log(
pub struct Builder { pub struct Builder {
dispatch: fern::Dispatch, dispatch: fern::Dispatch,
rotation_strategy: RotationStrategy, rotation_strategy: RotationStrategy,
timezone_strategy: TimezoneStrategy,
max_file_size: u128, max_file_size: u128,
targets: Vec<LogTarget>, targets: Vec<LogTarget>,
} }
@ -157,7 +177,7 @@ impl Default for Builder {
let dispatch = fern::Dispatch::new().format(move |out, message, record| { let dispatch = fern::Dispatch::new().format(move |out, message, record| {
out.finish(format_args!( out.finish(format_args!(
"{}[{}][{}] {}", "{}[{}][{}] {}",
time::OffsetDateTime::now_utc().format(&format).unwrap(), DEFAULT_TIMEZONE_STRATEGY.get_now().format(&format).unwrap(),
record.target(), record.target(),
record.level(), record.level(),
message message
@ -166,6 +186,7 @@ impl Default for Builder {
Self { Self {
dispatch, dispatch,
rotation_strategy: DEFAULT_ROTATION_STRATEGY, rotation_strategy: DEFAULT_ROTATION_STRATEGY,
timezone_strategy: DEFAULT_TIMEZONE_STRATEGY,
max_file_size: DEFAULT_MAX_FILE_SIZE, max_file_size: DEFAULT_MAX_FILE_SIZE,
targets: DEFAULT_LOG_TARGETS.into(), targets: DEFAULT_LOG_TARGETS.into(),
} }
@ -182,6 +203,24 @@ impl Builder {
self self
} }
pub fn timezone_strategy(mut self, timezone_strategy: TimezoneStrategy) -> Self {
self.timezone_strategy = timezone_strategy.clone();
let format =
time::format_description::parse("[[[year]-[month]-[day]][[[hour]:[minute]:[second]]")
.unwrap();
self.dispatch = fern::Dispatch::new().format(move |out, message, record| {
out.finish(format_args!(
"{}[{}][{}] {}",
timezone_strategy.get_now().format(&format).unwrap(),
record.target(),
record.level(),
message
))
});
self
}
pub fn max_file_size(mut self, max_file_size: u128) -> Self { pub fn max_file_size(mut self, max_file_size: u128) -> Self {
self.max_file_size = max_file_size; self.max_file_size = max_file_size;
self self
@ -228,10 +267,12 @@ impl Builder {
let format = let format =
time::format_description::parse("[[[year]-[month]-[day]][[[hour]:[minute]:[second]]") time::format_description::parse("[[[year]-[month]-[day]][[[hour]:[minute]:[second]]")
.unwrap(); .unwrap();
let timezone_strategy = self.timezone_strategy.clone();
self.format(move |out, message, record| { self.format(move |out, message, record| {
out.finish(format_args!( out.finish(format_args!(
"{}[{}][{}] {}", "{}[{}][{}] {}",
time::OffsetDateTime::now_utc().format(&format).unwrap(), timezone_strategy.get_now().format(&format).unwrap(),
record.target(), record.target(),
colors.color(record.level()), colors.color(record.level()),
message message
@ -259,6 +300,7 @@ impl Builder {
&path, &path,
app_name, app_name,
&self.rotation_strategy, &self.rotation_strategy,
&self.timezone_strategy,
self.max_file_size, self.max_file_size,
)?)? )?)?
.into() .into()
@ -273,6 +315,7 @@ impl Builder {
&path, &path,
app_name, app_name,
&self.rotation_strategy, &self.rotation_strategy,
&self.timezone_strategy,
self.max_file_size, self.max_file_size,
)?)? )?)?
.into() .into()
@ -306,6 +349,7 @@ fn get_log_file_path(
dir: &impl AsRef<Path>, dir: &impl AsRef<Path>,
app_name: &str, app_name: &str,
rotation_strategy: &RotationStrategy, rotation_strategy: &RotationStrategy,
timezone_strategy: &TimezoneStrategy,
max_file_size: u128, max_file_size: u128,
) -> plugin::Result<PathBuf> { ) -> plugin::Result<PathBuf> {
let path = dir.as_ref().join(format!("{app_name}.log")); let path = dir.as_ref().join(format!("{app_name}.log"));
@ -318,7 +362,8 @@ fn get_log_file_path(
let to = dir.as_ref().join(format!( let to = dir.as_ref().join(format!(
"{}_{}.log", "{}_{}.log",
app_name, app_name,
time::OffsetDateTime::now_utc() timezone_strategy
.get_now()
.format( .format(
&time::format_description::parse( &time::format_description::parse(
"[year]-[month]-[day]_[hour]-[minute]-[second]" "[year]-[month]-[day]_[hour]-[minute]-[second]"

Loading…
Cancel
Save