From a4ac54cf0ec17afabcd3de3056ea5a067c526693 Mon Sep 17 00:00:00 2001 From: Tu Nguyen Date: Mon, 27 May 2024 22:43:20 +0700 Subject: [PATCH 01/10] Add date time for log file --- examples/sample_config.yml | 2 +- src/append/file.rs | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/examples/sample_config.yml b/examples/sample_config.yml index 84bb9133..a3d67e17 100644 --- a/examples/sample_config.yml +++ b/examples/sample_config.yml @@ -8,7 +8,7 @@ appenders: level: info file: kind: file - path: "log/file.log" + path: "log/file-{d}.log" encoder: pattern: "[{d(%Y-%m-%dT%H:%M:%S%.6f)} {h({l}):<5.5} {M}] {m}{n}" rollingfile: diff --git a/src/append/file.rs b/src/append/file.rs index 3f345e7d..538b3808 100644 --- a/src/append/file.rs +++ b/src/append/file.rs @@ -10,6 +10,7 @@ use std::{ io::{self, BufWriter, Write}, path::{Path, PathBuf}, }; +use chrono::prelude::Local; #[cfg(feature = "config_parsing")] use crate::config::{Deserialize, Deserializers}; @@ -91,7 +92,17 @@ impl FileAppenderBuilder { pub fn build>(self, path: P) -> io::Result { let path_cow = path.as_ref().to_string_lossy(); let path: PathBuf = expand_env_vars(path_cow).as_ref().into(); - if let Some(parent) = path.parent() { + + // Get the current date + let local_date = Local::now().format("%Y-%m-%d_%H-%M-%S").to_string(); + + // Replace the placeholder if it exists + let path_with_date = if path.to_string_lossy().contains("{d}") { + PathBuf::from(path.to_string_lossy().replace("{d}", &local_date)) + } else { + path.clone() + }; + if let Some(parent) = path_with_date.parent() { fs::create_dir_all(parent)?; } let file = OpenOptions::new() @@ -99,7 +110,7 @@ impl FileAppenderBuilder { .append(self.append) .truncate(!self.append) .create(true) - .open(&path)?; + .open(&path_with_date)?; Ok(FileAppender { path, From edbf815e8bccb65f4b096c8dbc5bf1906053234c Mon Sep 17 00:00:00 2001 From: Tu Nguyen Date: Mon, 27 May 2024 23:17:40 +0700 Subject: [PATCH 02/10] use same format date time with chrono crate --- examples/sample_config.yml | 2 +- src/append/file.rs | 54 ++++++++++++++++++++++++++------------ 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/examples/sample_config.yml b/examples/sample_config.yml index a3d67e17..71814abd 100644 --- a/examples/sample_config.yml +++ b/examples/sample_config.yml @@ -8,7 +8,7 @@ appenders: level: info file: kind: file - path: "log/file-{d}.log" + path: "log/file-{%Y-%m-%d_%H-%M-%S}.log" encoder: pattern: "[{d(%Y-%m-%dT%H:%M:%S%.6f)} {h({l}):<5.5} {M}] {m}{n}" rollingfile: diff --git a/src/append/file.rs b/src/append/file.rs index 538b3808..7617a5f5 100644 --- a/src/append/file.rs +++ b/src/append/file.rs @@ -2,6 +2,7 @@ //! //! Requires the `file_appender` feature. +use chrono::prelude::Local; use derivative::Derivative; use log::Record; use parking_lot::Mutex; @@ -10,7 +11,6 @@ use std::{ io::{self, BufWriter, Write}, path::{Path, PathBuf}, }; -use chrono::prelude::Local; #[cfg(feature = "config_parsing")] use crate::config::{Deserialize, Deserializers}; @@ -18,7 +18,7 @@ use crate::config::{Deserialize, Deserializers}; use crate::encode::EncoderConfig; use crate::{ - append::{env_util::expand_env_vars, Append}, + append::Append, encode::{pattern::PatternEncoder, writer::simple::SimpleWriter, Encode}, }; @@ -90,19 +90,9 @@ impl FileAppenderBuilder { /// will be resolved. Note that if the variable fails to resolve, /// $ENV{name_here} will NOT be replaced in the path. pub fn build>(self, path: P) -> io::Result { - let path_cow = path.as_ref().to_string_lossy(); - let path: PathBuf = expand_env_vars(path_cow).as_ref().into(); - - // Get the current date - let local_date = Local::now().format("%Y-%m-%d_%H-%M-%S").to_string(); - - // Replace the placeholder if it exists - let path_with_date = if path.to_string_lossy().contains("{d}") { - PathBuf::from(path.to_string_lossy().replace("{d}", &local_date)) - } else { - path.clone() - }; - if let Some(parent) = path_with_date.parent() { + let new_path = self.date_time_format(path); + + if let Some(parent) = new_path.parent() { fs::create_dir_all(parent)?; } let file = OpenOptions::new() @@ -110,16 +100,46 @@ impl FileAppenderBuilder { .append(self.append) .truncate(!self.append) .create(true) - .open(&path_with_date)?; + .open(&new_path)?; Ok(FileAppender { - path, + path: new_path, file: Mutex::new(SimpleWriter(BufWriter::with_capacity(1024, file))), encoder: self .encoder .unwrap_or_else(|| Box::::default()), }) } + + fn date_time_format>(&self, path: P) -> PathBuf { + let path_cow = path.as_ref().to_string_lossy(); + + // Locate the start and end of the placeholder + let new_path = if let Some(start) = path_cow.find('{') { + if let Some(end) = path_cow.find('}') { + // Extract the date format string + let date_format = &path_cow[start + 1..end]; + + // Get the current date and time + let now = Local::now(); + + // Format the current date and time + let formatted_date = now.format(date_format).to_string(); + + // Create the new path string by replacing the placeholder with the formatted date + let mut new_path_str = path_cow.to_string(); + new_path_str.replace_range(start..=end, &formatted_date); + + // Convert the resulting string to PathBuf + PathBuf::from(new_path_str) + } else { + PathBuf::from(path_cow.to_string()) + } + } else { + PathBuf::from(path_cow.to_string()) + }; + new_path + } } /// A deserializer for the `FileAppender`. From 2f97acba10b6b948078fb00fc53c5d4207cf8ef9 Mon Sep 17 00:00:00 2001 From: Tu Nguyen Date: Thu, 30 May 2024 09:42:20 +0700 Subject: [PATCH 03/10] keep environment variables as part of the path --- src/append/file.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/append/file.rs b/src/append/file.rs index 7617a5f5..15c50860 100644 --- a/src/append/file.rs +++ b/src/append/file.rs @@ -18,7 +18,7 @@ use crate::config::{Deserialize, Deserializers}; use crate::encode::EncoderConfig; use crate::{ - append::Append, + append::{env_util::expand_env_vars, Append}, encode::{pattern::PatternEncoder, writer::simple::SimpleWriter, Encode}, }; @@ -113,9 +113,8 @@ impl FileAppenderBuilder { fn date_time_format>(&self, path: P) -> PathBuf { let path_cow = path.as_ref().to_string_lossy(); - // Locate the start and end of the placeholder - let new_path = if let Some(start) = path_cow.find('{') { + if let Some(start) = path_cow.find('{') { if let Some(end) = path_cow.find('}') { // Extract the date format string let date_format = &path_cow[start + 1..end]; @@ -131,14 +130,10 @@ impl FileAppenderBuilder { new_path_str.replace_range(start..=end, &formatted_date); // Convert the resulting string to PathBuf - PathBuf::from(new_path_str) - } else { - PathBuf::from(path_cow.to_string()) + return expand_env_vars(new_path_str).as_ref().into(); } - } else { - PathBuf::from(path_cow.to_string()) - }; - new_path + } + expand_env_vars(path_cow).as_ref().into() } } From 2b04121adf70a12ad88322734c05f3729c50143c Mon Sep 17 00:00:00 2001 From: Tu Nguyen Date: Thu, 30 May 2024 09:57:03 +0700 Subject: [PATCH 04/10] Update documentation for date and time file format --- docs/Configuration.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/Configuration.md b/docs/Configuration.md index a7dd94a3..b8874a05 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -131,6 +131,9 @@ my_console_appender: The _path_ field is required and accepts environment variables of the form `$ENV{name_here}`. The path can be relative or absolute. +The _path_ field also supports date/time formats such as `{%Y-%m-%d_%H-%M-%S}`. Refer +to [chrono format](https://docs.rs/chrono/latest/chrono/format/strftime/index.html) for date and time formatting syntax + The _encoder_ field is optional and can consist of multiple fields. Refer to the [encoder](#encoder) documention. @@ -140,7 +143,7 @@ append to the log file if it exists, false will truncate the existing file. ```yml my_file_appender: kind: file - path: $ENV{PWD}/log/test.log + path: $ENV{PWD}/log/test_{%Y-%m-%d_%H-%M-%S}.log append: true ``` From 5a8cbe71381fcb23cec33bf4f205d736fef65b17 Mon Sep 17 00:00:00 2001 From: Tu Nguyen Date: Fri, 31 May 2024 10:45:30 +0700 Subject: [PATCH 05/10] extract the environment path first --- src/append/file.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/append/file.rs b/src/append/file.rs index 15c50860..8f9ca3e6 100644 --- a/src/append/file.rs +++ b/src/append/file.rs @@ -113,11 +113,15 @@ impl FileAppenderBuilder { fn date_time_format>(&self, path: P) -> PathBuf { let path_cow = path.as_ref().to_string_lossy(); + // Extract the environment path first + let env_path: PathBuf = expand_env_vars(path_cow).as_ref().into(); + + let date_time_path = env_path.to_str().unwrap(); // Locate the start and end of the placeholder - if let Some(start) = path_cow.find('{') { - if let Some(end) = path_cow.find('}') { + if let Some(start) = date_time_path.find('{') { + if let Some(end) = date_time_path.find('}') { // Extract the date format string - let date_format = &path_cow[start + 1..end]; + let date_format = &date_time_path[start + 1..end]; // Get the current date and time let now = Local::now(); @@ -126,14 +130,14 @@ impl FileAppenderBuilder { let formatted_date = now.format(date_format).to_string(); // Create the new path string by replacing the placeholder with the formatted date - let mut new_path_str = path_cow.to_string(); + let mut new_path_str = date_time_path.to_string(); new_path_str.replace_range(start..=end, &formatted_date); // Convert the resulting string to PathBuf return expand_env_vars(new_path_str).as_ref().into(); } } - expand_env_vars(path_cow).as_ref().into() + expand_env_vars(date_time_path).as_ref().into() } } From 42f991d15166850888c972e215f5a54a6c0b1ce0 Mon Sep 17 00:00:00 2001 From: Tu Nguyen Date: Mon, 3 Jun 2024 08:56:22 +0700 Subject: [PATCH 06/10] Don't need to try and expand environment variables again --- src/append/file.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/append/file.rs b/src/append/file.rs index 8f9ca3e6..4a4ab80b 100644 --- a/src/append/file.rs +++ b/src/append/file.rs @@ -134,10 +134,10 @@ impl FileAppenderBuilder { new_path_str.replace_range(start..=end, &formatted_date); // Convert the resulting string to PathBuf - return expand_env_vars(new_path_str).as_ref().into(); + return PathBuf::from(new_path_str); } } - expand_env_vars(date_time_path).as_ref().into() + PathBuf::from(date_time_path) } } From 041b3e38530512bce2ce8da5fd4c326683273f31 Mon Sep 17 00:00:00 2001 From: Tu Nguyen Date: Mon, 8 Jul 2024 19:53:47 +0700 Subject: [PATCH 07/10] add pattern {} for log file name --- docs/Configuration.md | 4 ++-- examples/sample_config.yml | 2 +- src/append/file.rs | 7 ++++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/Configuration.md b/docs/Configuration.md index b8874a05..fda7de40 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -131,7 +131,7 @@ my_console_appender: The _path_ field is required and accepts environment variables of the form `$ENV{name_here}`. The path can be relative or absolute. -The _path_ field also supports date/time formats such as `{%Y-%m-%d_%H-%M-%S}`. Refer +The _path_ field also supports date/time formats such as `$TIME{chrono_format}`. Refer to [chrono format](https://docs.rs/chrono/latest/chrono/format/strftime/index.html) for date and time formatting syntax The _encoder_ field is optional and can consist of multiple fields. Refer to @@ -143,7 +143,7 @@ append to the log file if it exists, false will truncate the existing file. ```yml my_file_appender: kind: file - path: $ENV{PWD}/log/test_{%Y-%m-%d_%H-%M-%S}.log + path: $ENV{PWD}/log/test_$TIME{%Y-%m-%d_%H-%M-%S}.log append: true ``` diff --git a/examples/sample_config.yml b/examples/sample_config.yml index 71814abd..553dac61 100644 --- a/examples/sample_config.yml +++ b/examples/sample_config.yml @@ -8,7 +8,7 @@ appenders: level: info file: kind: file - path: "log/file-{%Y-%m-%d_%H-%M-%S}.log" + path: "log/file-$TIME{%Y-%m-%d_%H-%M-%S}.log" encoder: pattern: "[{d(%Y-%m-%dT%H:%M:%S%.6f)} {h({l}):<5.5} {M}] {m}{n}" rollingfile: diff --git a/src/append/file.rs b/src/append/file.rs index 4a4ab80b..6ce5c2c2 100644 --- a/src/append/file.rs +++ b/src/append/file.rs @@ -118,10 +118,11 @@ impl FileAppenderBuilder { let date_time_path = env_path.to_str().unwrap(); // Locate the start and end of the placeholder - if let Some(start) = date_time_path.find('{') { - if let Some(end) = date_time_path.find('}') { + if let Some(start) = date_time_path.find("$TIME{") { + if let Some(end) = date_time_path[start..].find('}') { + let end = start + end; // Extract the date format string - let date_format = &date_time_path[start + 1..end]; + let date_format = &date_time_path[start + 6..end]; // Get the current date and time let now = Local::now(); From ff4bd9baa3c91622920d3adf63b45bc43d8b17c9 Mon Sep 17 00:00:00 2001 From: Tu Nguyen Date: Tue, 9 Jul 2024 10:52:22 +0700 Subject: [PATCH 08/10] add comment for TIME and add const TIME pattern --- src/append/file.rs | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/append/file.rs b/src/append/file.rs index 6ce5c2c2..c0d1c6e4 100644 --- a/src/append/file.rs +++ b/src/append/file.rs @@ -12,6 +12,11 @@ use std::{ path::{Path, PathBuf}, }; +const TIME_PREFIX: &str = "$TIME{"; +const TIME_PREFIX_LEN: usize = TIME_PREFIX.len(); +const TIME_SUFFIX: char = '}'; +const TIME_SUFFIX_LEN: usize = 1; + #[cfg(feature = "config_parsing")] use crate::config::{Deserialize, Deserializers}; #[cfg(feature = "config_parsing")] @@ -85,10 +90,16 @@ impl FileAppenderBuilder { } /// Consumes the `FileAppenderBuilder`, producing a `FileAppender`. - /// The path argument can contain environment variables of the form $ENV{name_here}, - /// where 'name_here' will be the name of the environment variable that - /// will be resolved. Note that if the variable fails to resolve, - /// $ENV{name_here} will NOT be replaced in the path. + /// The path argument can contain special patterns that will be resolved: + /// + /// - `$ENV{name_here}`: This pattern will be replaced by `name_here`. + /// where 'name_here' will be the name of the environment variable that + /// will be resolved. Note that if the variable fails to resolve, + /// $ENV{name_here} will NOT be replaced in the path. + /// - `$TIME{chrono_format}`: This pattern will be replaced by `chrono_format`. + /// where 'chrono_format' will be date/time format from chrono crate. Note + /// that if the chrono_format fails to resolve, $TIME{chrono_format} will + /// NOT be replaced in the path. pub fn build>(self, path: P) -> io::Result { let new_path = self.date_time_format(path); @@ -118,11 +129,11 @@ impl FileAppenderBuilder { let date_time_path = env_path.to_str().unwrap(); // Locate the start and end of the placeholder - if let Some(start) = date_time_path.find("$TIME{") { - if let Some(end) = date_time_path[start..].find('}') { + if let Some(start) = date_time_path.find(TIME_PREFIX) { + if let Some(end) = date_time_path[start..].find(TIME_SUFFIX) { let end = start + end; // Extract the date format string - let date_format = &date_time_path[start + 6..end]; + let date_format = &date_time_path[start + TIME_PREFIX_LEN..end]; // Get the current date and time let now = Local::now(); @@ -132,7 +143,7 @@ impl FileAppenderBuilder { // Create the new path string by replacing the placeholder with the formatted date let mut new_path_str = date_time_path.to_string(); - new_path_str.replace_range(start..=end, &formatted_date); + new_path_str.replace_range(start..end + TIME_SUFFIX_LEN, &formatted_date); // Convert the resulting string to PathBuf return PathBuf::from(new_path_str); From 3b4832877844a23eb3eba2487d81677314b6fc1f Mon Sep 17 00:00:00 2001 From: Tu Nguyen Date: Wed, 10 Jul 2024 11:02:06 +0700 Subject: [PATCH 09/10] Improve date/time pattern and add unit tests: - Seperate TIME and ENV pattern - Support multiple placeholders - Add unit tests for: valid, invalid and multiple placeholders --- src/append/file.rs | 72 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/src/append/file.rs b/src/append/file.rs index c0d1c6e4..4afa5b5d 100644 --- a/src/append/file.rs +++ b/src/append/file.rs @@ -101,9 +101,13 @@ impl FileAppenderBuilder { /// that if the chrono_format fails to resolve, $TIME{chrono_format} will /// NOT be replaced in the path. pub fn build>(self, path: P) -> io::Result { - let new_path = self.date_time_format(path); + let path_cow = path.as_ref().to_string_lossy(); + // Expand environment variables in the path + let expanded_env_path: PathBuf = expand_env_vars(path_cow).as_ref().into(); + // Apply the date/time format to the path + let final_path = self.date_time_format(expanded_env_path); - if let Some(parent) = new_path.parent() { + if let Some(parent) = final_path.parent() { fs::create_dir_all(parent)?; } let file = OpenOptions::new() @@ -111,10 +115,10 @@ impl FileAppenderBuilder { .append(self.append) .truncate(!self.append) .create(true) - .open(&new_path)?; + .open(&final_path)?; Ok(FileAppender { - path: new_path, + path: final_path, file: Mutex::new(SimpleWriter(BufWriter::with_capacity(1024, file))), encoder: self .encoder @@ -122,14 +126,10 @@ impl FileAppenderBuilder { }) } - fn date_time_format>(&self, path: P) -> PathBuf { - let path_cow = path.as_ref().to_string_lossy(); - // Extract the environment path first - let env_path: PathBuf = expand_env_vars(path_cow).as_ref().into(); - - let date_time_path = env_path.to_str().unwrap(); + fn date_time_format(&self, path: PathBuf) -> PathBuf { + let mut date_time_path = path.to_str().unwrap().to_string(); // Locate the start and end of the placeholder - if let Some(start) = date_time_path.find(TIME_PREFIX) { + while let Some(start) = date_time_path.find(TIME_PREFIX) { if let Some(end) = date_time_path[start..].find(TIME_SUFFIX) { let end = start + end; // Extract the date format string @@ -141,12 +141,8 @@ impl FileAppenderBuilder { // Format the current date and time let formatted_date = now.format(date_format).to_string(); - // Create the new path string by replacing the placeholder with the formatted date - let mut new_path_str = date_time_path.to_string(); - new_path_str.replace_range(start..end + TIME_SUFFIX_LEN, &formatted_date); - - // Convert the resulting string to PathBuf - return PathBuf::from(new_path_str); + // replacing the placeholder with the formatted date + date_time_path.replace_range(start..end + TIME_SUFFIX_LEN, &formatted_date); } } PathBuf::from(date_time_path) @@ -222,4 +218,46 @@ mod test { .build(tempdir.path().join("foo.log")) .unwrap(); } + + #[test] + fn test_date_time_format_with_valid_format() { + let current_time = Local::now().format("%Y-%m-%d").to_string(); + let tempdir = tempfile::tempdir().unwrap(); + let builder = FileAppender::builder() + .build(tempdir.path().join("foo").join("bar").join("logs/log-$TIME{%Y-%m-%d}.log")) + .unwrap(); + let expected_path = tempdir.path().join(format!("foo/bar/logs/log-{}.log", current_time)); + assert_eq!(builder.path, expected_path); + } + + #[test] + fn test_date_time_format_with_invalid_format() { + let tempdir = tempfile::tempdir().unwrap(); + let builder = FileAppender::builder() + .build(tempdir.path().join("foo").join("bar").join("logs/log-$TIME{INVALID}.log")) + .unwrap(); + let expected_path = tempdir.path().join("foo/bar/logs/log-INVALID.log"); + assert_eq!(builder.path, expected_path); + } + + #[test] + fn test_date_time_format_without_placeholder() { + let tempdir = tempfile::tempdir().unwrap(); + let builder = FileAppender::builder() + .build(tempdir.path().join("foo").join("bar").join("bar.log")) + .unwrap(); + let expected_path = tempdir.path().join("foo/bar/bar.log"); + assert_eq!(builder.path, expected_path); + } + + #[test] + fn test_date_time_format_with_multiple_placeholders() { + let current_time = Local::now().format("%Y-%m-%d").to_string(); + let tempdir = tempfile::tempdir().unwrap(); + let builder = FileAppender::builder() + .build(tempdir.path().join("foo").join("bar").join("logs-$TIME{%Y-%m-%d}/log-$TIME{%Y-%m-%d}.log")) + .unwrap(); + let expected_path = tempdir.path().join(format!("foo/bar/logs-{}/log-{}.log", current_time, current_time)); + assert_eq!(builder.path, expected_path); + } } From c98af237ab2e9c4ca641ae12950af09bad870677 Mon Sep 17 00:00:00 2001 From: Tu Nguyen Date: Fri, 12 Jul 2024 16:12:10 +0700 Subject: [PATCH 10/10] fix fmt issues --- src/append/file.rs | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/append/file.rs b/src/append/file.rs index 4afa5b5d..c658baef 100644 --- a/src/append/file.rs +++ b/src/append/file.rs @@ -224,9 +224,17 @@ mod test { let current_time = Local::now().format("%Y-%m-%d").to_string(); let tempdir = tempfile::tempdir().unwrap(); let builder = FileAppender::builder() - .build(tempdir.path().join("foo").join("bar").join("logs/log-$TIME{%Y-%m-%d}.log")) - .unwrap(); - let expected_path = tempdir.path().join(format!("foo/bar/logs/log-{}.log", current_time)); + .build( + tempdir + .path() + .join("foo") + .join("bar") + .join("logs/log-$TIME{%Y-%m-%d}.log"), + ) + .unwrap(); + let expected_path = tempdir + .path() + .join(format!("foo/bar/logs/log-{}.log", current_time)); assert_eq!(builder.path, expected_path); } @@ -234,8 +242,14 @@ mod test { fn test_date_time_format_with_invalid_format() { let tempdir = tempfile::tempdir().unwrap(); let builder = FileAppender::builder() - .build(tempdir.path().join("foo").join("bar").join("logs/log-$TIME{INVALID}.log")) - .unwrap(); + .build( + tempdir + .path() + .join("foo") + .join("bar") + .join("logs/log-$TIME{INVALID}.log"), + ) + .unwrap(); let expected_path = tempdir.path().join("foo/bar/logs/log-INVALID.log"); assert_eq!(builder.path, expected_path); } @@ -244,8 +258,8 @@ mod test { fn test_date_time_format_without_placeholder() { let tempdir = tempfile::tempdir().unwrap(); let builder = FileAppender::builder() - .build(tempdir.path().join("foo").join("bar").join("bar.log")) - .unwrap(); + .build(tempdir.path().join("foo").join("bar").join("bar.log")) + .unwrap(); let expected_path = tempdir.path().join("foo/bar/bar.log"); assert_eq!(builder.path, expected_path); } @@ -255,9 +269,18 @@ mod test { let current_time = Local::now().format("%Y-%m-%d").to_string(); let tempdir = tempfile::tempdir().unwrap(); let builder = FileAppender::builder() - .build(tempdir.path().join("foo").join("bar").join("logs-$TIME{%Y-%m-%d}/log-$TIME{%Y-%m-%d}.log")) - .unwrap(); - let expected_path = tempdir.path().join(format!("foo/bar/logs-{}/log-{}.log", current_time, current_time)); + .build( + tempdir + .path() + .join("foo") + .join("bar") + .join("logs-$TIME{%Y-%m-%d}/log-$TIME{%Y-%m-%d}.log"), + ) + .unwrap(); + let expected_path = tempdir.path().join(format!( + "foo/bar/logs-{}/log-{}.log", + current_time, current_time + )); assert_eq!(builder.path, expected_path); } }