From 53398da58b8802d64994ff97f3818c75b66357a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Wed, 15 Dec 2021 15:58:49 +0100 Subject: [PATCH 01/22] Implement compression --- tracing-appender/Cargo.toml | 1 + tracing-appender/src/inner.rs | 36 +++++++++++++----- tracing-appender/src/lib.rs | 2 + tracing-appender/src/rolling.rs | 66 ++++++++++++++++++++++----------- tracing-appender/src/writer.rs | 18 +++++++++ 5 files changed, 91 insertions(+), 32 deletions(-) create mode 100644 tracing-appender/src/writer.rs diff --git a/tracing-appender/Cargo.toml b/tracing-appender/Cargo.toml index 1023fc412b..9a48724c56 100644 --- a/tracing-appender/Cargo.toml +++ b/tracing-appender/Cargo.toml @@ -23,6 +23,7 @@ rust-version = "1.51.0" [dependencies] crossbeam-channel = "0.5.0" time = { version = "0.3", default-features = false, features = ["formatting"] } +flate2 = { version = "1.0.22" } [dependencies.tracing-subscriber] path = "../tracing-subscriber" diff --git a/tracing-appender/src/inner.rs b/tracing-appender/src/inner.rs index 1c40eeaae8..43fbc74ce9 100644 --- a/tracing-appender/src/inner.rs +++ b/tracing-appender/src/inner.rs @@ -6,14 +6,18 @@ use std::fmt::Debug; use std::fs::{File, OpenOptions}; use std::path::Path; use time::OffsetDateTime; +use flate2::Compression; +use flate2::write::GzEncoder; +use crate::writer::WriterChannel; #[derive(Debug)] pub(crate) struct InnerAppender { log_directory: String, log_filename_prefix: String, - writer: BufWriter, + writer: WriterChannel, next_date: Option, rotation: Rotation, + compress: bool } impl io::Write for InnerAppender { @@ -23,7 +27,7 @@ impl io::Write for InnerAppender { } fn flush(&mut self) -> io::Result<()> { - self.writer.flush() + self.writer.get_writer().flush() } } @@ -32,12 +36,14 @@ impl InnerAppender { log_directory: &Path, log_filename_prefix: &Path, rotation: Rotation, - now: OffsetDateTime, + now: OffsetDateTime ) -> io::Result { let log_directory = log_directory.to_str().unwrap(); - let log_filename_prefix = log_filename_prefix.to_str().unwrap(); - let filename = rotation.join_date(log_filename_prefix, &now); + let compress = log_filename_prefix.to_str().unwrap().ends_with(".gz"); + let log_filename_prefix = log_filename_prefix.to_str().unwrap().trim_end_matches(".gz"); + + let filename = rotation.join_date(log_filename_prefix, &now, compress); let next_date = rotation.next_date(&now); Ok(InnerAppender { @@ -46,6 +52,7 @@ impl InnerAppender { writer: create_writer(log_directory, &filename)?, next_date, rotation, + compress }) } @@ -54,18 +61,19 @@ impl InnerAppender { // and proceed with the write. let buf_len = buf.len(); self.refresh_writer(date); - self.writer.write_all(buf).map(|_| buf_len) + self.writer.get_writer().write_all(buf).map(|_| buf_len) } fn refresh_writer(&mut self, now: OffsetDateTime) { if self.should_rollover(now) { - let filename = self.rotation.join_date(&self.log_filename_prefix, &now); + let filename = self.rotation.join_date( + &self.log_filename_prefix, &now, self.compress); self.next_date = self.rotation.next_date(&now); match create_writer(&self.log_directory, &filename) { Ok(writer) => { - if let Err(err) = self.writer.flush() { + if let Err(err) = self.writer.get_writer().flush() { eprintln!("Couldn't flush previous writer: {}", err); } self.writer = writer @@ -84,9 +92,17 @@ impl InnerAppender { } } -fn create_writer(directory: &str, filename: &str) -> io::Result> { +fn create_writer(directory: &str, filename: &str) -> io::Result { let file_path = Path::new(directory).join(filename); - Ok(BufWriter::new(open_file_create_parent_dirs(&file_path)?)) + let file = open_file_create_parent_dirs(&file_path)?; + if filename.ends_with(".gz") { + let buf = BufWriter::new(file); + let gzfile = GzEncoder::new(buf, Compression::default()); + let writer = BufWriter::new(gzfile); + Ok(WriterChannel::CompressedFileGzip(writer)) + } else { + Ok(WriterChannel::File(BufWriter::new(file))) + } } fn open_file_create_parent_dirs(path: &Path) -> io::Result { diff --git a/tracing-appender/src/lib.rs b/tracing-appender/src/lib.rs index 536c894a7b..25b349d9eb 100644 --- a/tracing-appender/src/lib.rs +++ b/tracing-appender/src/lib.rs @@ -161,6 +161,8 @@ pub mod rolling; mod worker; +mod writer; + /// Convenience function for creating a non-blocking, off-thread writer. /// /// See the [`non_blocking` module's docs][mod@non_blocking]'s for more details. diff --git a/tracing-appender/src/rolling.rs b/tracing-appender/src/rolling.rs index b38afbb740..4afa9099dc 100644 --- a/tracing-appender/src/rolling.rs +++ b/tracing-appender/src/rolling.rs @@ -86,7 +86,7 @@ impl RollingFileAppender { directory.as_ref(), file_name_prefix.as_ref(), rotation, - OffsetDateTime::now_utc(), + OffsetDateTime::now_utc() ) .expect("Failed to create appender"), } @@ -283,7 +283,7 @@ enum RotationKind { Minutely, Hourly, Daily, - Never, + Never } impl Rotation { @@ -331,7 +331,7 @@ impl Rotation { } } - pub(crate) fn join_date(&self, filename: &str, date: &OffsetDateTime) -> String { + pub(crate) fn join_date(&self, filename: &str, date: &OffsetDateTime, compress: bool) -> String { match *self { Rotation::MINUTELY => { let format = format_description::parse("[year]-[month]-[day]-[hour]-[minute]") @@ -340,7 +340,7 @@ impl Rotation { let date = date .format(&format) .expect("Unable to format OffsetDateTime; this is a bug in tracing-appender"); - format!("{}.{}", filename, date) + Rotation::format_params(filename, compress, date) } Rotation::HOURLY => { let format = format_description::parse("[year]-[month]-[day]-[hour]") @@ -349,7 +349,7 @@ impl Rotation { let date = date .format(&format) .expect("Unable to format OffsetDateTime; this is a bug in tracing-appender"); - format!("{}.{}", filename, date) + Rotation::format_params(filename, compress, date) } Rotation::DAILY => { let format = format_description::parse("[year]-[month]-[day]") @@ -357,9 +357,21 @@ impl Rotation { let date = date .format(&format) .expect("Unable to format OffsetDateTime; this is a bug in tracing-appender"); - format!("{}.{}", filename, date) + Rotation::format_params(filename, compress, date) } - Rotation::NEVER => filename.to_string(), + Rotation::NEVER => if compress { + format!("{}.gz", filename.to_string()) + } else { + filename.to_string() + }, + } + } + + fn format_params(filename: &str, compress: bool, date: String) -> String { + if compress { + format!("{}.{}.gz", filename, date) + } else { + format!("{}.{}", filename, date) } } } @@ -392,7 +404,7 @@ mod test { appender.flush().expect("Failed to flush!"); } - fn test_appender(rotation: Rotation, file_prefix: &str) { + fn test_appender(rotation: Rotation, file_prefix: &str, compress: bool) { let directory = tempfile::tempdir().expect("failed to create tempdir"); let mut appender = RollingFileAppender::new(rotation, directory.path(), file_prefix); @@ -407,23 +419,17 @@ mod test { #[test] fn write_minutely_log() { - test_appender(Rotation::HOURLY, "minutely.log"); + test_appender(Rotation::HOURLY, "minutely.log", false); } #[test] - fn write_hourly_log() { - test_appender(Rotation::HOURLY, "hourly.log"); - } + fn write_hourly_log() { test_appender(Rotation::HOURLY, "hourly.log", false); } #[test] - fn write_daily_log() { - test_appender(Rotation::DAILY, "daily.log"); - } + fn write_daily_log() { test_appender(Rotation::DAILY, "daily.log", false); } #[test] - fn write_never_log() { - test_appender(Rotation::NEVER, "never.log"); - } + fn write_never_log() { test_appender(Rotation::NEVER, "never.log", false); } #[test] fn test_rotations() { @@ -468,19 +474,35 @@ mod test { let now = OffsetDateTime::parse("2020-02-01 10:01:00 +00:00:00", &format).unwrap(); // per-minute - let path = Rotation::MINUTELY.join_date("app.log", &now); + let path = Rotation::MINUTELY.join_date("app.log", &now, false); assert_eq!("app.log.2020-02-01-10-01", path); // per-hour - let path = Rotation::HOURLY.join_date("app.log", &now); + let path = Rotation::HOURLY.join_date("app.log", &now, false); assert_eq!("app.log.2020-02-01-10", path); // per-day - let path = Rotation::DAILY.join_date("app.log", &now); + let path = Rotation::DAILY.join_date("app.log", &now, false); assert_eq!("app.log.2020-02-01", path); // never - let path = Rotation::NEVER.join_date("app.log", &now); + let path = Rotation::NEVER.join_date("app.log", &now, false); assert_eq!("app.log", path); + + // per-minute compressed + let path = Rotation::MINUTELY.join_date("app.log", &now, true); + assert_eq!("app.log.2020-02-01-10-01.gz", path); + + // per-hour compressed + let path = Rotation::HOURLY.join_date("app.log", &now, true); + assert_eq!("app.log.2020-02-01-10.gz", path); + + // per-day compressed + let path = Rotation::DAILY.join_date("app.log", &now, true); + assert_eq!("app.log.2020-02-01.gz", path); + + // never compressed + let path = Rotation::NEVER.join_date("app.log", &now, true); + assert_eq!("app.log.gz", path) } } diff --git a/tracing-appender/src/writer.rs b/tracing-appender/src/writer.rs new file mode 100644 index 0000000000..6da5bdd0d9 --- /dev/null +++ b/tracing-appender/src/writer.rs @@ -0,0 +1,18 @@ +use std::io::{BufWriter, Write}; +use std::fs::File; +use flate2::write::GzEncoder; + +#[derive(Debug)] +pub enum WriterChannel { + File(BufWriter), + CompressedFileGzip(BufWriter>>), +} + +impl WriterChannel { + pub fn get_writer(&mut self) -> &mut dyn Write { + match self { + WriterChannel::File(x) => x, + WriterChannel::CompressedFileGzip(x) => x, + } + } +} \ No newline at end of file From 992982627ff4df12e494f48f20ba56bd2e1502fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Wed, 15 Dec 2021 16:06:50 +0100 Subject: [PATCH 02/22] Format --- tracing-appender/src/rolling.rs | 4 ++-- tracing-appender/src/writer.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tracing-appender/src/rolling.rs b/tracing-appender/src/rolling.rs index 4afa9099dc..c86ccdd0f1 100644 --- a/tracing-appender/src/rolling.rs +++ b/tracing-appender/src/rolling.rs @@ -86,7 +86,7 @@ impl RollingFileAppender { directory.as_ref(), file_name_prefix.as_ref(), rotation, - OffsetDateTime::now_utc() + OffsetDateTime::now_utc(), ) .expect("Failed to create appender"), } @@ -283,7 +283,7 @@ enum RotationKind { Minutely, Hourly, Daily, - Never + Never, } impl Rotation { diff --git a/tracing-appender/src/writer.rs b/tracing-appender/src/writer.rs index 6da5bdd0d9..170c8c6f36 100644 --- a/tracing-appender/src/writer.rs +++ b/tracing-appender/src/writer.rs @@ -15,4 +15,4 @@ impl WriterChannel { WriterChannel::CompressedFileGzip(x) => x, } } -} \ No newline at end of file +} From ef1bb1007a3a38c88d4d2804d79e99d1557bc70f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Thu, 23 Dec 2021 12:10:00 +0100 Subject: [PATCH 03/22] Compiles after implementing io::Write for &WriterChannel --- tracing-appender/Cargo.toml | 5 ++++- tracing-appender/src/builder.rs | 10 ++++++---- tracing-appender/src/rolling.rs | 17 +++++++++-------- tracing-appender/src/writer.rs | 32 ++++++++++++++++++++++++++------ 4 files changed, 45 insertions(+), 19 deletions(-) diff --git a/tracing-appender/Cargo.toml b/tracing-appender/Cargo.toml index fcf9273724..6b28260e28 100644 --- a/tracing-appender/Cargo.toml +++ b/tracing-appender/Cargo.toml @@ -23,7 +23,7 @@ rust-version = "1.51.0" [dependencies] crossbeam-channel = "0.5.0" time = { version = "0.3", default-features = false, features = ["formatting"] } -flate2 = { version = "1.0.22" } +flate2 = { optional = true, version = "1.0.22" } parking_lot = { optional = true, version = "0.11.2" } [dependencies.tracing-subscriber] @@ -36,3 +36,6 @@ features = ["fmt", "std"] tracing = { path = "../tracing", version = "0.2" } time = { version = "0.3", default-features = false, features = ["formatting", "parsing"] } tempfile = "3" + +[features] +compression = ["flate2"] diff --git a/tracing-appender/src/builder.rs b/tracing-appender/src/builder.rs index b05959352d..336769bce1 100644 --- a/tracing-appender/src/builder.rs +++ b/tracing-appender/src/builder.rs @@ -1,5 +1,3 @@ -use std::io; -use std::path::Path; use std::sync::atomic::AtomicUsize; use time::OffsetDateTime; use crate::rolling::{create_writer_file, Inner, RollingFileAppender, Rotation}; @@ -25,7 +23,9 @@ impl RollingFileAppenderBuilder { log_directory: None, log_filename_prefix: None, rotation: None, - next_date: None + next_date: None, + #[cfg(feature = "compression")] + compression: None } } @@ -78,7 +78,9 @@ impl RollingFileAppenderBuilder { log_directory, log_filename_prefix, next_date, - rotation + rotation, + #[cfg(feature = "compression")] + compression: self.compression }, writer, } diff --git a/tracing-appender/src/rolling.rs b/tracing-appender/src/rolling.rs index c401550756..a9e3da0769 100644 --- a/tracing-appender/src/rolling.rs +++ b/tracing-appender/src/rolling.rs @@ -34,9 +34,10 @@ use std::{ path::Path, sync::atomic::{AtomicUsize, Ordering}, }; -use std::borrow::BorrowMut; use time::{format_description, Duration, OffsetDateTime, Time}; use crate::builder::RollingFileAppenderBuilder; +#[cfg(feature = "compression")] +use crate::compression::CompressionConfig; use crate::writer::WriterChannel; /// A file appender with the ability to rotate log files at a fixed schedule. @@ -156,11 +157,11 @@ impl io::Write for RollingFileAppender { debug_assert!(_did_cas, "if we have &mut access to the appender, no other thread can have advanced the timestamp..."); self.state.refresh_writer(now, writer); } - writer.get_writer().write(buf) + writer.write(buf) } fn flush(&mut self) -> io::Result<()> { - self.writer.get_mut().get_writer().flush() + self.writer.get_mut().flush() } } @@ -458,11 +459,11 @@ impl Rotation { impl io::Write for RollingWriter<'_> { fn write(&mut self, buf: &[u8]) -> io::Result { - (&*self.0).get_writer().write(buf) + (&*self.0).write(buf) } fn flush(&mut self) -> io::Result<()> { - (&*self.0).get_writer().flush() + (&*self.0).flush() } } @@ -506,11 +507,11 @@ impl Inner { fn refresh_writer_channel(file: &mut WriterChannel, writer: io::Result) { match writer { - Ok(new_file) => { - if let Err(err) = file.get_writer().flush() { + Ok(new_writer) => { + if let Err(err) = file.flush() { eprintln!("Couldn't flush previous writer: {}", err); } - *file = new_file; + *file = new_writer; } Err(err) => eprintln!("Couldn't create writer for logs: {}", err), } diff --git a/tracing-appender/src/writer.rs b/tracing-appender/src/writer.rs index cc7e286082..644a6d5e99 100644 --- a/tracing-appender/src/writer.rs +++ b/tracing-appender/src/writer.rs @@ -8,6 +8,8 @@ use crate::sync::RwLock; use crate::rolling::create_writer_file; #[cfg(feature = "compression")] use flate2::write::GzEncoder; +#[cfg(feature = "compression")] +use crate::compression::CompressionConfig; #[derive(Debug)] pub enum WriterChannel { @@ -51,22 +53,40 @@ impl WriterChannel { let writer = BufWriter::new(gzfile); Ok(WriterChannel::CompressedFileGzip(writer)) } +} - pub fn get_writer(&mut self) -> &mut dyn Write { +impl io::Write for WriterChannel { + fn write(&mut self, buf: &[u8]) -> io::Result { match self { - WriterChannel::File(x) => x, + WriterChannel::File(f) => f.write(buf), #[cfg(feature = "compression")] - WriterChannel::CompressedFileGzip(x) => x, + WriterChannel::CompressedFileGzip(buf) => f.write(buf) + } + } + + fn flush(&mut self) -> io::Result<()> { + match self { + WriterChannel::File(f) => f.flush(), + #[cfg(feature = "compression")] + WriterChannel::CompressedFileGzip(buf) => buf.flush() } } } -impl io::Write for WriterChannel { +impl io::Write for &WriterChannel { fn write(&mut self, buf: &[u8]) -> io::Result { - self.borrow_mut().write(buf) + match self { + WriterChannel::File(f) => (&*f).write(buf), + #[cfg(feature = "compression")] + WriterChannel::CompressedFileGzip(buf) => f.write(buf) + } } fn flush(&mut self) -> io::Result<()> { - self.borrow_mut().flush() + match self { + WriterChannel::File(f) => (&*f).flush(), + #[cfg(feature = "compression")] + WriterChannel::CompressedFileGzip(buf) => buf.flush() + } } } From 759327788369aaa20da373249cc762c270283d07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Thu, 23 Dec 2021 12:36:35 +0100 Subject: [PATCH 04/22] Add shortcuts for compression options --- tracing-appender/src/compression.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tracing-appender/src/compression.rs b/tracing-appender/src/compression.rs index fc4be9cf80..5857c45982 100644 --- a/tracing-appender/src/compression.rs +++ b/tracing-appender/src/compression.rs @@ -59,4 +59,21 @@ pub struct GzipCompression { /// Data structure to pass compression parameters pub enum CompressionConfig { Gzip(GzipCompression) -} \ No newline at end of file +} + +mod compression_options { + use super::*; + pub const GZIP_NONE: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::None) }); + pub const GZIP_FAST: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::Fast) }); + pub const GZIP_BEST: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::Best) }); + pub const GZIP_0: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level0) }); + pub const GZIP_1: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level1) }); + pub const GZIP_2: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level2) }); + pub const GZIP_3: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level3) }); + pub const GZIP_4: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level4) }); + pub const GZIP_5: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level5) }); + pub const GZIP_6: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level6) }); + pub const GZIP_7: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level7) }); + pub const GZIP_8: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level8) }); + pub const GZIP_9: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level9) }); +} From 74d36558565cdfe88ebc34e8fe94702d99fb2aa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Fri, 24 Dec 2021 00:46:26 +0100 Subject: [PATCH 05/22] Fix formatting --- tracing-appender/src/builder.rs | 31 ++++++---- tracing-appender/src/compression.rs | 96 ++++++++++++++++++----------- tracing-appender/src/rolling.rs | 76 +++++++++++++---------- tracing-appender/src/writer.rs | 45 +++++++------- 4 files changed, 144 insertions(+), 104 deletions(-) diff --git a/tracing-appender/src/builder.rs b/tracing-appender/src/builder.rs index 336769bce1..c9708370fc 100644 --- a/tracing-appender/src/builder.rs +++ b/tracing-appender/src/builder.rs @@ -1,9 +1,9 @@ -use std::sync::atomic::AtomicUsize; -use time::OffsetDateTime; use crate::rolling::{create_writer_file, Inner, RollingFileAppender, Rotation}; use crate::sync::RwLock; +use std::sync::atomic::AtomicUsize; +use time::OffsetDateTime; -#[cfg(feature="compression")] +#[cfg(feature = "compression")] use crate::compression::CompressionConfig; use crate::writer::WriterChannel; @@ -14,7 +14,7 @@ pub struct RollingFileAppenderBuilder { rotation: Option, next_date: Option, #[cfg(feature = "compression")] - compression: Option + compression: Option, } impl RollingFileAppenderBuilder { @@ -25,7 +25,7 @@ impl RollingFileAppenderBuilder { rotation: None, next_date: None, #[cfg(feature = "compression")] - compression: None + compression: None, } } @@ -57,15 +57,22 @@ impl RollingFileAppenderBuilder { pub fn build(self) -> RollingFileAppender { let now = OffsetDateTime::now_utc(); - let log_directory = self.log_directory.expect("log_directory is required to build RollingFileAppender"); - let log_filename_prefix = self.log_filename_prefix.expect("log_filename_prefix is required to build RollingFileAppender"); - let rotation = self.rotation.expect("rotation is required to build RollingFileAppender"); + let log_directory = self + .log_directory + .expect("log_directory is required to build RollingFileAppender"); + let log_filename_prefix = self + .log_filename_prefix + .expect("log_filename_prefix is required to build RollingFileAppender"); + let rotation = self + .rotation + .expect("rotation is required to build RollingFileAppender"); let filename = rotation.join_date(log_filename_prefix.as_str(), &now, false); let next_date = rotation.next_date(&now); - let writer = RwLock::new( - WriterChannel::File(create_writer_file(log_directory.as_str(), &filename).expect("failed to create appender")) - ); + let writer = RwLock::new(WriterChannel::File( + create_writer_file(log_directory.as_str(), &filename) + .expect("failed to create appender"), + )); let next_date = AtomicUsize::new( next_date @@ -80,7 +87,7 @@ impl RollingFileAppenderBuilder { next_date, rotation, #[cfg(feature = "compression")] - compression: self.compression + compression: self.compression, }, writer, } diff --git a/tracing-appender/src/compression.rs b/tracing-appender/src/compression.rs index 5857c45982..c4c6888aaf 100644 --- a/tracing-appender/src/compression.rs +++ b/tracing-appender/src/compression.rs @@ -16,64 +16,86 @@ pub enum GzipCompressionLevelNumerical { Level6, Level7, Level8, - Level9 + Level9, } pub enum GzipCompressionLevel { Literal(GzipCompressionLevelLiteral), - Numerical(GzipCompressionLevelNumerical) + Numerical(GzipCompressionLevelNumerical), } impl Into for GzipCompressionLevel { fn into(self) -> Compression { match GzipCompressionLevel { - GzipCompressionLevel::Literal(lit) => { - match lit { - GzipCompressionLevelLiteral::None => Compression::none(), - GzipCompressionLevelLiteral::Fast => Compression::fast(), - GzipCompressionLevelLiteral::Best => Compression::best() - } + GzipCompressionLevel::Literal(lit) => match lit { + GzipCompressionLevelLiteral::None => Compression::none(), + GzipCompressionLevelLiteral::Fast => Compression::fast(), + GzipCompressionLevelLiteral::Best => Compression::best(), + }, + GzipCompressionLevel::Numerical(num) => match num { + GzipCompressionLevelNumerical::Level0 => Compression(0), + GzipCompressionLevelNumerical::Level1 => Compression(1), + GzipCompressionLevelNumerical::Level2 => Compression(2), + GzipCompressionLevelNumerical::Level3 => Compression(3), + GzipCompressionLevelNumerical::Level4 => Compression(4), + GzipCompressionLevelNumerical::Level5 => Compression(5), + GzipCompressionLevelNumerical::Level6 => Compression(6), + GzipCompressionLevelNumerical::Level7 => Compression(7), + GzipCompressionLevelNumerical::Level8 => Compression(8), + GzipCompressionLevelNumerical::Level9 => Compression(9), }, - GzipCompressionLevel::Numerical(num) => { - match num { - GzipCompressionLevelNumerical::Level0 => Compression(0), - GzipCompressionLevelNumerical::Level1 => Compression(1), - GzipCompressionLevelNumerical::Level2 => Compression(2), - GzipCompressionLevelNumerical::Level3 => Compression(3), - GzipCompressionLevelNumerical::Level4 => Compression(4), - GzipCompressionLevelNumerical::Level5 => Compression(5), - GzipCompressionLevelNumerical::Level6 => Compression(6), - GzipCompressionLevelNumerical::Level7 => Compression(7), - GzipCompressionLevelNumerical::Level8 => Compression(8), - GzipCompressionLevelNumerical::Level9 => Compression(9) - } - } } } } pub struct GzipCompression { - pub level: GzipCompressionLevel + pub level: GzipCompressionLevel, } /// Data structure to pass compression parameters pub enum CompressionConfig { - Gzip(GzipCompression) + Gzip(GzipCompression), } mod compression_options { use super::*; - pub const GZIP_NONE: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::None) }); - pub const GZIP_FAST: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::Fast) }); - pub const GZIP_BEST: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::Best) }); - pub const GZIP_0: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level0) }); - pub const GZIP_1: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level1) }); - pub const GZIP_2: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level2) }); - pub const GZIP_3: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level3) }); - pub const GZIP_4: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level4) }); - pub const GZIP_5: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level5) }); - pub const GZIP_6: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level6) }); - pub const GZIP_7: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level7) }); - pub const GZIP_8: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level8) }); - pub const GZIP_9: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level9) }); + pub const GZIP_NONE: CompressionConfig = CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::None), + }); + pub const GZIP_FAST: CompressionConfig = CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::Fast), + }); + pub const GZIP_BEST: CompressionConfig = CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::Best), + }); + pub const GZIP_0: CompressionConfig = CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level0), + }); + pub const GZIP_1: CompressionConfig = CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level1), + }); + pub const GZIP_2: CompressionConfig = CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level2), + }); + pub const GZIP_3: CompressionConfig = CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level3), + }); + pub const GZIP_4: CompressionConfig = CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level4), + }); + pub const GZIP_5: CompressionConfig = CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level5), + }); + pub const GZIP_6: CompressionConfig = CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level6), + }); + pub const GZIP_7: CompressionConfig = CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level7), + }); + pub const GZIP_8: CompressionConfig = CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level8), + }); + pub const GZIP_9: CompressionConfig = CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level9), + }); } diff --git a/tracing-appender/src/rolling.rs b/tracing-appender/src/rolling.rs index a9e3da0769..ab863ec441 100644 --- a/tracing-appender/src/rolling.rs +++ b/tracing-appender/src/rolling.rs @@ -26,7 +26,11 @@ //! let file_appender = RollingFileAppender::new(Rotation::HOURLY, "/some/directory", "prefix.log"); //! # } //! ``` +use crate::builder::RollingFileAppenderBuilder; +#[cfg(feature = "compression")] +use crate::compression::CompressionConfig; use crate::sync::{RwLock, RwLockReadGuard}; +use crate::writer::WriterChannel; use std::{ fmt::Debug, fs::{self, File, OpenOptions}, @@ -35,10 +39,6 @@ use std::{ sync::atomic::{AtomicUsize, Ordering}, }; use time::{format_description, Duration, OffsetDateTime, Time}; -use crate::builder::RollingFileAppenderBuilder; -#[cfg(feature = "compression")] -use crate::compression::CompressionConfig; -use crate::writer::WriterChannel; /// A file appender with the ability to rotate log files at a fixed schedule. /// @@ -106,7 +106,7 @@ pub(crate) struct Inner { pub(crate) rotation: Rotation, pub(crate) next_date: AtomicUsize, #[cfg(feature = "compression")] - pub(crate) compression: Option + pub(crate) compression: Option, } // === impl RollingFileAppender === @@ -410,7 +410,12 @@ impl Rotation { } } - pub(crate) fn join_date(&self, filename: &str, date: &OffsetDateTime, compress: bool) -> String { + pub(crate) fn join_date( + &self, + filename: &str, + date: &OffsetDateTime, + compress: bool, + ) -> String { match *self { Rotation::MINUTELY => { let format = format_description::parse("[year]-[month]-[day]-[hour]-[minute]") @@ -438,11 +443,13 @@ impl Rotation { .expect("Unable to format OffsetDateTime; this is a bug in tracing-appender"); Rotation::format_params(filename, compress, date) } - Rotation::NEVER => if compress { - format!("{}.gz", filename.to_string()) - } else { - filename.to_string() - }, + Rotation::NEVER => { + if compress { + format!("{}.gz", filename.to_string()) + } else { + filename.to_string() + } + } } } @@ -470,37 +477,34 @@ impl io::Write for RollingWriter<'_> { // === impl Inner === impl Inner { - #[cfg(feature = "compression")] - fn refresh_writer(&self, - now: OffsetDateTime, - file: &mut WriterChannel, - compression: CompressionConfig) { + fn refresh_writer( + &self, + now: OffsetDateTime, + file: &mut WriterChannel, + compression: CompressionConfig, + ) { debug_assert!(self.should_rollover(now)); - let filename = self.rotation.join_date(&self.log_filename_prefix, &now, false); + let filename = self + .rotation + .join_date(&self.log_filename_prefix, &now, false); - let writer = WriterChannel::new_with_compression( - &self.log_directory, - &filename, - compression - ); + let writer = + WriterChannel::new_with_compression(&self.log_directory, &filename, compression); Self::refresh_writer_channel(file, writer); } #[cfg(not(feature = "compression"))] - fn refresh_writer(&self, - now: OffsetDateTime, - file: &mut WriterChannel) { + fn refresh_writer(&self, now: OffsetDateTime, file: &mut WriterChannel) { debug_assert!(self.should_rollover(now)); - let filename = self.rotation.join_date(&self.log_filename_prefix, &now, false); + let filename = self + .rotation + .join_date(&self.log_filename_prefix, &now, false); - let writer = WriterChannel::new_without_compression( - &self.log_directory, - &filename, - ); + let writer = WriterChannel::new_without_compression(&self.log_directory, &filename); Self::refresh_writer_channel(file, writer) } @@ -606,13 +610,19 @@ mod test { } #[test] - fn write_hourly_log() { test_appender(Rotation::HOURLY, "hourly.log", false); } + fn write_hourly_log() { + test_appender(Rotation::HOURLY, "hourly.log", false); + } #[test] - fn write_daily_log() { test_appender(Rotation::DAILY, "daily.log", false); } + fn write_daily_log() { + test_appender(Rotation::DAILY, "daily.log", false); + } #[test] - fn write_never_log() { test_appender(Rotation::NEVER, "never.log", false); } + fn write_never_log() { + test_appender(Rotation::NEVER, "never.log", false); + } #[test] fn test_rotations() { diff --git a/tracing-appender/src/writer.rs b/tracing-appender/src/writer.rs index 644a6d5e99..96ba291385 100644 --- a/tracing-appender/src/writer.rs +++ b/tracing-appender/src/writer.rs @@ -1,15 +1,15 @@ -use std::{fs, io}; +#[cfg(feature = "compression")] +use crate::compression::CompressionConfig; +use crate::rolling::create_writer_file; +use crate::sync::RwLock; +#[cfg(feature = "compression")] +use flate2::write::GzEncoder; use std::borrow::BorrowMut; -use std::io::{BufWriter, Write}; use std::fs::{File, OpenOptions}; +use std::io::{BufWriter, Write}; use std::ops::{Deref, DerefMut}; use std::path::Path; -use crate::sync::RwLock; -use crate::rolling::create_writer_file; -#[cfg(feature = "compression")] -use flate2::write::GzEncoder; -#[cfg(feature = "compression")] -use crate::compression::CompressionConfig; +use std::{fs, io}; #[derive(Debug)] pub enum WriterChannel { @@ -20,11 +20,11 @@ pub enum WriterChannel { impl WriterChannel { #[cfg(feature = "compression")] - pub fn new(directory: &str, - filename: &str, - #[cfg(feature = "compression")] - compression: CompressionConfig) -> io::Result { - + pub fn new( + directory: &str, + filename: &str, + #[cfg(feature = "compression")] compression: CompressionConfig, + ) -> io::Result { if let Some(compression) = compression { Self::new_with_compression(directory, filename, compression) } else { @@ -33,8 +33,7 @@ impl WriterChannel { } #[cfg(not(feature = "compression"))] - pub fn new(directory: &str, - filename: &str) -> io::Result { + pub fn new(directory: &str, filename: &str) -> io::Result { Self::new_without_compression(directory, filename) } @@ -44,9 +43,11 @@ impl WriterChannel { } #[cfg(feature = "compression")] - pub fn new_with_compression(directory: &str, - filename: &str, - compression: CompressionConfig) -> io::Result { + pub fn new_with_compression( + directory: &str, + filename: &str, + compression: CompressionConfig, + ) -> io::Result { let file = create_writer_file(directory, filename)?; let buf = BufWriter::new(file); let gzfile = GzEncoder::new(buf, compression.into()); @@ -60,7 +61,7 @@ impl io::Write for WriterChannel { match self { WriterChannel::File(f) => f.write(buf), #[cfg(feature = "compression")] - WriterChannel::CompressedFileGzip(buf) => f.write(buf) + WriterChannel::CompressedFileGzip(buf) => f.write(buf), } } @@ -68,7 +69,7 @@ impl io::Write for WriterChannel { match self { WriterChannel::File(f) => f.flush(), #[cfg(feature = "compression")] - WriterChannel::CompressedFileGzip(buf) => buf.flush() + WriterChannel::CompressedFileGzip(buf) => buf.flush(), } } } @@ -78,7 +79,7 @@ impl io::Write for &WriterChannel { match self { WriterChannel::File(f) => (&*f).write(buf), #[cfg(feature = "compression")] - WriterChannel::CompressedFileGzip(buf) => f.write(buf) + WriterChannel::CompressedFileGzip(buf) => f.write(buf), } } @@ -86,7 +87,7 @@ impl io::Write for &WriterChannel { match self { WriterChannel::File(f) => (&*f).flush(), #[cfg(feature = "compression")] - WriterChannel::CompressedFileGzip(buf) => buf.flush() + WriterChannel::CompressedFileGzip(buf) => buf.flush(), } } } From 6601402980ec878d14eb92bd2d54fbfed8c34c05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Fri, 24 Dec 2021 12:45:32 +0100 Subject: [PATCH 06/22] Review fixes - to be continued --- tracing-appender/Cargo.toml | 6 +-- tracing-appender/src/builder.rs | 59 +++++++++++------------------ tracing-appender/src/compression.rs | 38 +++++++++++++------ tracing-appender/src/lib.rs | 2 +- tracing-appender/src/rolling.rs | 23 ++++++----- tracing-appender/src/writer.rs | 38 ++++++++++++------- 6 files changed, 89 insertions(+), 77 deletions(-) diff --git a/tracing-appender/Cargo.toml b/tracing-appender/Cargo.toml index 6b28260e28..4579997d37 100644 --- a/tracing-appender/Cargo.toml +++ b/tracing-appender/Cargo.toml @@ -20,6 +20,9 @@ keywords = ["logging", "tracing", "file-appender", "non-blocking-writer"] edition = "2018" rust-version = "1.51.0" +[features] +compression = ["flate2"] + [dependencies] crossbeam-channel = "0.5.0" time = { version = "0.3", default-features = false, features = ["formatting"] } @@ -36,6 +39,3 @@ features = ["fmt", "std"] tracing = { path = "../tracing", version = "0.2" } time = { version = "0.3", default-features = false, features = ["formatting", "parsing"] } tempfile = "3" - -[features] -compression = ["flate2"] diff --git a/tracing-appender/src/builder.rs b/tracing-appender/src/builder.rs index c9708370fc..3f61f33ee4 100644 --- a/tracing-appender/src/builder.rs +++ b/tracing-appender/src/builder.rs @@ -1,3 +1,4 @@ +use std::path::Path; use crate::rolling::{create_writer_file, Inner, RollingFileAppender, Rotation}; use crate::sync::RwLock; use std::sync::atomic::AtomicUsize; @@ -8,48 +9,40 @@ use crate::compression::CompressionConfig; use crate::writer::WriterChannel; + +#[derive(Debug)] pub struct RollingFileAppenderBuilder { - log_directory: Option, - log_filename_prefix: Option, + log_directory: String, + log_filename_prefix: String, rotation: Option, - next_date: Option, #[cfg(feature = "compression")] compression: Option, } impl RollingFileAppenderBuilder { - pub fn new() -> Self { + /// Creates an instance of RollingFileAppnderBuilder + pub fn new(log_directory: impl AsRef, + log_filename_prefix: impl AsRef) -> Self { + let log_directory = log_directory.as_ref().to_str().expect("Cannot convert log_directory Path to str").to_string(); + let log_filename_prefix = log_filename_prefix.as_ref().to_str().expect("Cannot convert log_filename_prefix Path to str").to_string(); RollingFileAppenderBuilder { - log_directory: None, - log_filename_prefix: None, + log_directory, + log_filename_prefix, rotation: None, - next_date: None, #[cfg(feature = "compression")] + #[cfg_attr(docsrs, doc(cfg(feature = "compression")))] compression: None, } } - pub fn log_directory(mut self, log_directory: String) -> Self { - self.log_directory = Some(log_directory); - self - } - - pub fn log_filename_prefix(mut self, log_filename_prefix: String) -> Self { - self.log_filename_prefix = Some(log_filename_prefix); - self - } - + /// Sets Rotation pub fn rotation(mut self, rotation: Rotation) -> Self { self.rotation = Some(rotation); self } - pub fn next_date(mut self, next_date: AtomicUsize) -> Self { - self.next_date = Some(next_date); - self - } - #[cfg(feature = "compression")] + #[cfg_attr(docsrs, doc(cfg(feature = "compression")))] pub fn compression(mut self, compression: CompressionConfig) -> Self { self.compression = Some(compression); self @@ -57,20 +50,12 @@ impl RollingFileAppenderBuilder { pub fn build(self) -> RollingFileAppender { let now = OffsetDateTime::now_utc(); - let log_directory = self - .log_directory - .expect("log_directory is required to build RollingFileAppender"); - let log_filename_prefix = self - .log_filename_prefix - .expect("log_filename_prefix is required to build RollingFileAppender"); - let rotation = self - .rotation - .expect("rotation is required to build RollingFileAppender"); - - let filename = rotation.join_date(log_filename_prefix.as_str(), &now, false); + let rotation = self.rotation.unwrap_or(Rotation::NEVER); + let filename = rotation.join_date(self.log_filename_prefix.as_str(), &now, false); let next_date = rotation.next_date(&now); + let writer = RwLock::new(WriterChannel::File( - create_writer_file(log_directory.as_str(), &filename) + create_writer_file(self.log_directory.as_str(), &filename) .expect("failed to create appender"), )); @@ -82,10 +67,10 @@ impl RollingFileAppenderBuilder { RollingFileAppender { state: Inner { - log_directory, - log_filename_prefix, + log_directory: self.log_directory, + log_filename_prefix: self.log_filename_prefix, next_date, - rotation, + rotation: rotation, #[cfg(feature = "compression")] compression: self.compression, }, diff --git a/tracing-appender/src/compression.rs b/tracing-appender/src/compression.rs index c4c6888aaf..4f203adc94 100644 --- a/tracing-appender/src/compression.rs +++ b/tracing-appender/src/compression.rs @@ -1,11 +1,13 @@ use flate2::Compression; +#[derive(Debug, Clone)] pub enum GzipCompressionLevelLiteral { None, Fast, Best, } +#[derive(Debug, Clone)] pub enum GzipCompressionLevelNumerical { Level0, Level1, @@ -19,6 +21,7 @@ pub enum GzipCompressionLevelNumerical { Level9, } +#[derive(Debug, Clone)] pub enum GzipCompressionLevel { Literal(GzipCompressionLevelLiteral), Numerical(GzipCompressionLevelNumerical), @@ -26,37 +29,50 @@ pub enum GzipCompressionLevel { impl Into for GzipCompressionLevel { fn into(self) -> Compression { - match GzipCompressionLevel { + match self { GzipCompressionLevel::Literal(lit) => match lit { GzipCompressionLevelLiteral::None => Compression::none(), GzipCompressionLevelLiteral::Fast => Compression::fast(), GzipCompressionLevelLiteral::Best => Compression::best(), }, GzipCompressionLevel::Numerical(num) => match num { - GzipCompressionLevelNumerical::Level0 => Compression(0), - GzipCompressionLevelNumerical::Level1 => Compression(1), - GzipCompressionLevelNumerical::Level2 => Compression(2), - GzipCompressionLevelNumerical::Level3 => Compression(3), - GzipCompressionLevelNumerical::Level4 => Compression(4), - GzipCompressionLevelNumerical::Level5 => Compression(5), - GzipCompressionLevelNumerical::Level6 => Compression(6), - GzipCompressionLevelNumerical::Level7 => Compression(7), - GzipCompressionLevelNumerical::Level8 => Compression(8), - GzipCompressionLevelNumerical::Level9 => Compression(9), + GzipCompressionLevelNumerical::Level0 => Compression::new(0), + GzipCompressionLevelNumerical::Level1 => Compression::new(1), + GzipCompressionLevelNumerical::Level2 => Compression::new(2), + GzipCompressionLevelNumerical::Level3 => Compression::new(3), + GzipCompressionLevelNumerical::Level4 => Compression::new(4), + GzipCompressionLevelNumerical::Level5 => Compression::new(5), + GzipCompressionLevelNumerical::Level6 => Compression::new(6), + GzipCompressionLevelNumerical::Level7 => Compression::new(7), + GzipCompressionLevelNumerical::Level8 => Compression::new(8), + GzipCompressionLevelNumerical::Level9 => Compression::new(9), }, } } } +#[derive(Debug, Clone)] pub struct GzipCompression { pub level: GzipCompressionLevel, } /// Data structure to pass compression parameters +#[derive(Debug, Clone)] pub enum CompressionConfig { Gzip(GzipCompression), } +impl CompressionConfig { + pub(crate) fn gz_compress_level(&self) -> Compression { + match self { + CompressionConfig::Gzip(gz) => { + let level = gz.level.into(); + level + } + } + } +} + mod compression_options { use super::*; pub const GZIP_NONE: CompressionConfig = CompressionConfig::Gzip(GzipCompression { diff --git a/tracing-appender/src/lib.rs b/tracing-appender/src/lib.rs index 55abdb8747..ae7ecb06f9 100644 --- a/tracing-appender/src/lib.rs +++ b/tracing-appender/src/lib.rs @@ -166,7 +166,7 @@ mod writer; #[cfg(feature = "compression")] mod compression; -mod builder; +pub mod builder; /// Convenience function for creating a non-blocking, off-thread writer. /// diff --git a/tracing-appender/src/rolling.rs b/tracing-appender/src/rolling.rs index ab863ec441..54e69643cf 100644 --- a/tracing-appender/src/rolling.rs +++ b/tracing-appender/src/rolling.rs @@ -39,6 +39,7 @@ use std::{ sync::atomic::{AtomicUsize, Ordering}, }; use time::{format_description, Duration, OffsetDateTime, Time}; +use tracing_subscriber::fmt::format::Writer; /// A file appender with the ability to rotate log files at a fixed schedule. /// @@ -88,6 +89,8 @@ use time::{format_description, Duration, OffsetDateTime, Time}; pub struct RollingFileAppender { pub(crate) state: Inner, pub(crate) writer: RwLock, + #[cfg(features = "compression")] + pub(crate) compression: Option, } /// A [writer] that writes to a rolling log file. @@ -140,10 +143,8 @@ impl RollingFileAppender { directory: impl AsRef, file_name_prefix: impl AsRef, ) -> RollingFileAppender { - RollingFileAppenderBuilder::new() + RollingFileAppenderBuilder::new(directory, file_name_prefix) .rotation(rotation) - .log_directory(directory.as_ref().to_str().unwrap().to_string()) - .log_filename_prefix(file_name_prefix.as_ref().to_str().unwrap().to_string()) .build() } } @@ -478,20 +479,18 @@ impl io::Write for RollingWriter<'_> { impl Inner { #[cfg(feature = "compression")] - fn refresh_writer( - &self, - now: OffsetDateTime, - file: &mut WriterChannel, - compression: CompressionConfig, - ) { + fn refresh_writer(&self, now: OffsetDateTime, file: &mut WriterChannel) { debug_assert!(self.should_rollover(now)); let filename = self .rotation .join_date(&self.log_filename_prefix, &now, false); - let writer = - WriterChannel::new_with_compression(&self.log_directory, &filename, compression); + let writer = if let Some(compression) = self.compression.clone() { + WriterChannel::new_with_compression(&self.log_directory, &filename, compression) + } else { + WriterChannel::new_without_compression(&self.log_directory, &filename) + }; Self::refresh_writer_channel(file, writer); } @@ -547,7 +546,7 @@ impl Inner { } } -pub fn create_writer_file(directory: &str, filename: &str) -> io::Result { +pub(crate) fn create_writer_file(directory: &str, filename: &str) -> io::Result { let path = Path::new(directory).join(filename); let mut open_options = OpenOptions::new(); open_options.append(true).create(true); diff --git a/tracing-appender/src/writer.rs b/tracing-appender/src/writer.rs index 96ba291385..7c964efc50 100644 --- a/tracing-appender/src/writer.rs +++ b/tracing-appender/src/writer.rs @@ -1,21 +1,29 @@ -#[cfg(feature = "compression")] -use crate::compression::CompressionConfig; use crate::rolling::create_writer_file; use crate::sync::RwLock; -#[cfg(feature = "compression")] -use flate2::write::GzEncoder; -use std::borrow::BorrowMut; +use std::borrow::{Borrow, BorrowMut}; use std::fs::{File, OpenOptions}; use std::io::{BufWriter, Write}; use std::ops::{Deref, DerefMut}; use std::path::Path; use std::{fs, io}; +#[cfg(feature = "compression")] +use flate2::write::GzEncoder; + +#[cfg(feature = "compression")] +use crate::compression::CompressionConfig; + +#[derive(Debug)] +struct CompressedGzip { + compression: CompressionConfig, + buffer: BufWriter>>, +} + #[derive(Debug)] pub enum WriterChannel { File(File), #[cfg(feature = "compression")] - CompressedFileGzip(BufWriter>>), + CompressedFileGzip(CompressedGzip), } impl WriterChannel { @@ -23,7 +31,7 @@ impl WriterChannel { pub fn new( directory: &str, filename: &str, - #[cfg(feature = "compression")] compression: CompressionConfig, + #[cfg(feature = "compression")] compression: Option, ) -> io::Result { if let Some(compression) = compression { Self::new_with_compression(directory, filename, compression) @@ -50,9 +58,13 @@ impl WriterChannel { ) -> io::Result { let file = create_writer_file(directory, filename)?; let buf = BufWriter::new(file); - let gzfile = GzEncoder::new(buf, compression.into()); + let gzfile = GzEncoder::new(buf, compression.gz_compress_level()); let writer = BufWriter::new(gzfile); - Ok(WriterChannel::CompressedFileGzip(writer)) + let compressed_gz = CompressedGzip { + compression: compression.clone(), + buffer: writer, + }; + Ok(WriterChannel::CompressedFileGzip(compressed_gz)) } } @@ -61,7 +73,7 @@ impl io::Write for WriterChannel { match self { WriterChannel::File(f) => f.write(buf), #[cfg(feature = "compression")] - WriterChannel::CompressedFileGzip(buf) => f.write(buf), + WriterChannel::CompressedFileGzip(gz) => gz.buffer.write(buf), } } @@ -69,7 +81,7 @@ impl io::Write for WriterChannel { match self { WriterChannel::File(f) => f.flush(), #[cfg(feature = "compression")] - WriterChannel::CompressedFileGzip(buf) => buf.flush(), + WriterChannel::CompressedFileGzip(gz) => gz.buffer.flush(), } } } @@ -79,7 +91,7 @@ impl io::Write for &WriterChannel { match self { WriterChannel::File(f) => (&*f).write(buf), #[cfg(feature = "compression")] - WriterChannel::CompressedFileGzip(buf) => f.write(buf), + WriterChannel::CompressedFileGzip(gz) => gz.buffer.write(buf), } } @@ -87,7 +99,7 @@ impl io::Write for &WriterChannel { match self { WriterChannel::File(f) => (&*f).flush(), #[cfg(feature = "compression")] - WriterChannel::CompressedFileGzip(buf) => buf.flush(), + WriterChannel::CompressedFileGzip(gz) => gz.buffer.flush(), } } } From 2c9f149ef5c2d3f46060d4249e9cb8060b4f3dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Fri, 24 Dec 2021 14:32:34 +0100 Subject: [PATCH 07/22] Format --- tracing-appender/src/builder.rs | 18 ++++++++++++------ tracing-appender/src/compression.rs | 2 +- tracing-appender/src/rolling.rs | 1 - tracing-appender/src/writer.rs | 10 +++------- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/tracing-appender/src/builder.rs b/tracing-appender/src/builder.rs index 3f61f33ee4..c26151f20b 100644 --- a/tracing-appender/src/builder.rs +++ b/tracing-appender/src/builder.rs @@ -1,6 +1,6 @@ -use std::path::Path; use crate::rolling::{create_writer_file, Inner, RollingFileAppender, Rotation}; use crate::sync::RwLock; +use std::path::Path; use std::sync::atomic::AtomicUsize; use time::OffsetDateTime; @@ -9,7 +9,6 @@ use crate::compression::CompressionConfig; use crate::writer::WriterChannel; - #[derive(Debug)] pub struct RollingFileAppenderBuilder { log_directory: String, @@ -21,10 +20,17 @@ pub struct RollingFileAppenderBuilder { impl RollingFileAppenderBuilder { /// Creates an instance of RollingFileAppnderBuilder - pub fn new(log_directory: impl AsRef, - log_filename_prefix: impl AsRef) -> Self { - let log_directory = log_directory.as_ref().to_str().expect("Cannot convert log_directory Path to str").to_string(); - let log_filename_prefix = log_filename_prefix.as_ref().to_str().expect("Cannot convert log_filename_prefix Path to str").to_string(); + pub fn new(log_directory: impl AsRef, log_filename_prefix: impl AsRef) -> Self { + let log_directory = log_directory + .as_ref() + .to_str() + .expect("Cannot convert log_directory Path to str") + .to_string(); + let log_filename_prefix = log_filename_prefix + .as_ref() + .to_str() + .expect("Cannot convert log_filename_prefix Path to str") + .to_string(); RollingFileAppenderBuilder { log_directory, log_filename_prefix, diff --git a/tracing-appender/src/compression.rs b/tracing-appender/src/compression.rs index 4f203adc94..98604c74fd 100644 --- a/tracing-appender/src/compression.rs +++ b/tracing-appender/src/compression.rs @@ -66,7 +66,7 @@ impl CompressionConfig { pub(crate) fn gz_compress_level(&self) -> Compression { match self { CompressionConfig::Gzip(gz) => { - let level = gz.level.into(); + let level = gz.level.clone().into(); level } } diff --git a/tracing-appender/src/rolling.rs b/tracing-appender/src/rolling.rs index 54e69643cf..a91bbc10a3 100644 --- a/tracing-appender/src/rolling.rs +++ b/tracing-appender/src/rolling.rs @@ -39,7 +39,6 @@ use std::{ sync::atomic::{AtomicUsize, Ordering}, }; use time::{format_description, Duration, OffsetDateTime, Time}; -use tracing_subscriber::fmt::format::Writer; /// A file appender with the ability to rotate log files at a fixed schedule. /// diff --git a/tracing-appender/src/writer.rs b/tracing-appender/src/writer.rs index 7c964efc50..aaa04de0fa 100644 --- a/tracing-appender/src/writer.rs +++ b/tracing-appender/src/writer.rs @@ -1,11 +1,7 @@ use crate::rolling::create_writer_file; -use crate::sync::RwLock; -use std::borrow::{Borrow, BorrowMut}; -use std::fs::{File, OpenOptions}; -use std::io::{BufWriter, Write}; -use std::ops::{Deref, DerefMut}; -use std::path::Path; -use std::{fs, io}; +use std::fs::File; +use std::io; +use std::io::BufWriter; #[cfg(feature = "compression")] use flate2::write::GzEncoder; From 248d923e0249c139ab663893bb76f0b495c1fc69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Fri, 24 Dec 2021 14:38:29 +0100 Subject: [PATCH 08/22] Use pub(crate) --- tracing-appender/src/compression.rs | 13 +++++++------ tracing-appender/src/writer.rs | 10 +++++----- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/tracing-appender/src/compression.rs b/tracing-appender/src/compression.rs index 98604c74fd..2cdf2c5948 100644 --- a/tracing-appender/src/compression.rs +++ b/tracing-appender/src/compression.rs @@ -1,14 +1,14 @@ use flate2::Compression; #[derive(Debug, Clone)] -pub enum GzipCompressionLevelLiteral { +enum GzipCompressionLevelLiteral { None, Fast, Best, } #[derive(Debug, Clone)] -pub enum GzipCompressionLevelNumerical { +enum GzipCompressionLevelNumerical { Level0, Level1, Level2, @@ -22,7 +22,7 @@ pub enum GzipCompressionLevelNumerical { } #[derive(Debug, Clone)] -pub enum GzipCompressionLevel { +enum GzipCompressionLevel { Literal(GzipCompressionLevelLiteral), Numerical(GzipCompressionLevelNumerical), } @@ -52,13 +52,14 @@ impl Into for GzipCompressionLevel { } #[derive(Debug, Clone)] -pub struct GzipCompression { +struct GzipCompression { pub level: GzipCompressionLevel, } /// Data structure to pass compression parameters #[derive(Debug, Clone)] -pub enum CompressionConfig { +#[non_exhaustive] +pub(crate) enum CompressionConfig { Gzip(GzipCompression), } @@ -73,7 +74,7 @@ impl CompressionConfig { } } -mod compression_options { +pub mod compression_options { use super::*; pub const GZIP_NONE: CompressionConfig = CompressionConfig::Gzip(GzipCompression { level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::None), diff --git a/tracing-appender/src/writer.rs b/tracing-appender/src/writer.rs index aaa04de0fa..76f9cc873e 100644 --- a/tracing-appender/src/writer.rs +++ b/tracing-appender/src/writer.rs @@ -16,7 +16,7 @@ struct CompressedGzip { } #[derive(Debug)] -pub enum WriterChannel { +pub(crate) enum WriterChannel { File(File), #[cfg(feature = "compression")] CompressedFileGzip(CompressedGzip), @@ -24,7 +24,7 @@ pub enum WriterChannel { impl WriterChannel { #[cfg(feature = "compression")] - pub fn new( + pub(crate) fn new( directory: &str, filename: &str, #[cfg(feature = "compression")] compression: Option, @@ -37,17 +37,17 @@ impl WriterChannel { } #[cfg(not(feature = "compression"))] - pub fn new(directory: &str, filename: &str) -> io::Result { + pub(crate) fn new(directory: &str, filename: &str) -> io::Result { Self::new_without_compression(directory, filename) } - pub fn new_without_compression(directory: &str, filename: &str) -> io::Result { + pub(crate) fn new_without_compression(directory: &str, filename: &str) -> io::Result { let file = create_writer_file(directory, filename)?; Ok(WriterChannel::File(file)) } #[cfg(feature = "compression")] - pub fn new_with_compression( + pub(crate) fn new_with_compression( directory: &str, filename: &str, compression: CompressionConfig, From 6f4a6062acc9bbcb79640b1a68d432fc9596f23a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Fri, 24 Dec 2021 15:09:06 +0100 Subject: [PATCH 09/22] Clean up compression options --- tracing-appender/src/builder.rs | 5 +- tracing-appender/src/compression.rs | 112 ++++++++++++++++------------ tracing-appender/src/writer.rs | 27 +++++-- 3 files changed, 89 insertions(+), 55 deletions(-) diff --git a/tracing-appender/src/builder.rs b/tracing-appender/src/builder.rs index c26151f20b..2f0cef69f3 100644 --- a/tracing-appender/src/builder.rs +++ b/tracing-appender/src/builder.rs @@ -6,6 +6,7 @@ use time::OffsetDateTime; #[cfg(feature = "compression")] use crate::compression::CompressionConfig; +use crate::compression::CompressionOption; use crate::writer::WriterChannel; @@ -49,8 +50,8 @@ impl RollingFileAppenderBuilder { #[cfg(feature = "compression")] #[cfg_attr(docsrs, doc(cfg(feature = "compression")))] - pub fn compression(mut self, compression: CompressionConfig) -> Self { - self.compression = Some(compression); + pub fn compression(mut self, compression: CompressionOption) -> Self { + self.compression = Some(compression.into()); self } diff --git a/tracing-appender/src/compression.rs b/tracing-appender/src/compression.rs index 2cdf2c5948..6bcfe23082 100644 --- a/tracing-appender/src/compression.rs +++ b/tracing-appender/src/compression.rs @@ -1,14 +1,14 @@ use flate2::Compression; #[derive(Debug, Clone)] -enum GzipCompressionLevelLiteral { +pub(crate) enum GzipCompressionLevelLiteral { None, Fast, Best, } #[derive(Debug, Clone)] -enum GzipCompressionLevelNumerical { +pub(crate) enum GzipCompressionLevelNumerical { Level0, Level1, Level2, @@ -22,7 +22,7 @@ enum GzipCompressionLevelNumerical { } #[derive(Debug, Clone)] -enum GzipCompressionLevel { +pub(crate) enum GzipCompressionLevel { Literal(GzipCompressionLevelLiteral), Numerical(GzipCompressionLevelNumerical), } @@ -52,8 +52,8 @@ impl Into for GzipCompressionLevel { } #[derive(Debug, Clone)] -struct GzipCompression { - pub level: GzipCompressionLevel, +pub(crate) struct GzipCompression { + pub(crate) level: GzipCompressionLevel, } /// Data structure to pass compression parameters @@ -74,45 +74,65 @@ impl CompressionConfig { } } -pub mod compression_options { - use super::*; - pub const GZIP_NONE: CompressionConfig = CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::None), - }); - pub const GZIP_FAST: CompressionConfig = CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::Fast), - }); - pub const GZIP_BEST: CompressionConfig = CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::Best), - }); - pub const GZIP_0: CompressionConfig = CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level0), - }); - pub const GZIP_1: CompressionConfig = CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level1), - }); - pub const GZIP_2: CompressionConfig = CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level2), - }); - pub const GZIP_3: CompressionConfig = CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level3), - }); - pub const GZIP_4: CompressionConfig = CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level4), - }); - pub const GZIP_5: CompressionConfig = CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level5), - }); - pub const GZIP_6: CompressionConfig = CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level6), - }); - pub const GZIP_7: CompressionConfig = CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level7), - }); - pub const GZIP_8: CompressionConfig = CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level8), - }); - pub const GZIP_9: CompressionConfig = CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level9), - }); +#[derive(Debug)] +pub enum CompressionOption { + GzipNone, + GzipFast, + GzipBest, + GzipLevel0, + GzipLevel1, + GzipLevel2, + GzipLevel3, + GzipLevel4, + GzipLevel5, + GzipLevel6, + GzipLevel7, + GzipLevel8, + GzipLevel9, +} + +impl Into for CompressionOption { + fn into(self) -> CompressionConfig { + match self { + CompressionOption::GzipNone => CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::None), + }), + CompressionOption::GzipFast => CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::Fast), + }), + CompressionOption::GzipBest => CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::Best), + }), + CompressionOption::GzipLevel0 => CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level0), + }), + CompressionOption::GzipLevel1 => CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level1), + }), + CompressionOption::GzipLevel2 => CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level2), + }), + CompressionOption::GzipLevel3 => CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level3), + }), + CompressionOption::GzipLevel4 => CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level4), + }), + CompressionOption::GzipLevel5 => CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level5), + }), + CompressionOption::GzipLevel6 => CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level6), + }), + CompressionOption::GzipLevel7 => CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level7), + }), + CompressionOption::GzipLevel8 => CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level8), + }), + CompressionOption::GzipLevel9 => CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level9), + }), + } + } } diff --git a/tracing-appender/src/writer.rs b/tracing-appender/src/writer.rs index 76f9cc873e..1dd4e2bd98 100644 --- a/tracing-appender/src/writer.rs +++ b/tracing-appender/src/writer.rs @@ -2,6 +2,7 @@ use crate::rolling::create_writer_file; use std::fs::File; use std::io; use std::io::BufWriter; +use std::sync::{Arc, RwLock}; #[cfg(feature = "compression")] use flate2::write::GzEncoder; @@ -10,9 +11,9 @@ use flate2::write::GzEncoder; use crate::compression::CompressionConfig; #[derive(Debug)] -struct CompressedGzip { +pub(crate) struct CompressedGzip { compression: CompressionConfig, - buffer: BufWriter>>, + buffer: Arc>>>>, } #[derive(Debug)] @@ -58,7 +59,7 @@ impl WriterChannel { let writer = BufWriter::new(gzfile); let compressed_gz = CompressedGzip { compression: compression.clone(), - buffer: writer, + buffer: Arc::new(RwLock::new(writer)), }; Ok(WriterChannel::CompressedFileGzip(compressed_gz)) } @@ -69,7 +70,10 @@ impl io::Write for WriterChannel { match self { WriterChannel::File(f) => f.write(buf), #[cfg(feature = "compression")] - WriterChannel::CompressedFileGzip(gz) => gz.buffer.write(buf), + WriterChannel::CompressedFileGzip(gz) => { + let mut buffer = gz.buffer.write().unwrap(); + buffer.write(buf) + } } } @@ -77,7 +81,10 @@ impl io::Write for WriterChannel { match self { WriterChannel::File(f) => f.flush(), #[cfg(feature = "compression")] - WriterChannel::CompressedFileGzip(gz) => gz.buffer.flush(), + WriterChannel::CompressedFileGzip(gz) => { + let mut buffer = gz.buffer.write().unwrap(); + buffer.flush() + } } } } @@ -87,7 +94,10 @@ impl io::Write for &WriterChannel { match self { WriterChannel::File(f) => (&*f).write(buf), #[cfg(feature = "compression")] - WriterChannel::CompressedFileGzip(gz) => gz.buffer.write(buf), + WriterChannel::CompressedFileGzip(gz) => { + let mut buffer = gz.buffer.write().unwrap(); + buffer.write(buf) + } } } @@ -95,7 +105,10 @@ impl io::Write for &WriterChannel { match self { WriterChannel::File(f) => (&*f).flush(), #[cfg(feature = "compression")] - WriterChannel::CompressedFileGzip(gz) => gz.buffer.flush(), + WriterChannel::CompressedFileGzip(gz) => { + let mut buffer = gz.buffer.write().unwrap(); + buffer.flush() + } } } } From 271e3b5c684e9eb75705ebbd2d646213c8dd2ee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Fri, 24 Dec 2021 15:30:21 +0100 Subject: [PATCH 10/22] Clean up imports --- tracing-appender/src/builder.rs | 2 ++ tracing-appender/src/writer.rs | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tracing-appender/src/builder.rs b/tracing-appender/src/builder.rs index 2f0cef69f3..743d474099 100644 --- a/tracing-appender/src/builder.rs +++ b/tracing-appender/src/builder.rs @@ -6,6 +6,8 @@ use time::OffsetDateTime; #[cfg(feature = "compression")] use crate::compression::CompressionConfig; + +#[cfg(feature = "compression")] use crate::compression::CompressionOption; use crate::writer::WriterChannel; diff --git a/tracing-appender/src/writer.rs b/tracing-appender/src/writer.rs index 1dd4e2bd98..100741a859 100644 --- a/tracing-appender/src/writer.rs +++ b/tracing-appender/src/writer.rs @@ -1,15 +1,16 @@ use crate::rolling::create_writer_file; use std::fs::File; use std::io; -use std::io::BufWriter; -use std::sync::{Arc, RwLock}; #[cfg(feature = "compression")] -use flate2::write::GzEncoder; +use { + crate::compression::CompressionConfig, + flate2::write::GzEncoder, + std::io::BufWriter, + std::sync::{Arc, RwLock}, +}; #[cfg(feature = "compression")] -use crate::compression::CompressionConfig; - #[derive(Debug)] pub(crate) struct CompressedGzip { compression: CompressionConfig, From 5ff40aa40b999a67cc41a9cfc22927fc418f4a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Mon, 27 Dec 2021 15:18:42 +0100 Subject: [PATCH 11/22] Add some docs --- tracing-appender/src/builder.rs | 17 ++++++++++++++++- tracing-appender/src/compression.rs | 18 +++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/tracing-appender/src/builder.rs b/tracing-appender/src/builder.rs index 743d474099..344a7d11f4 100644 --- a/tracing-appender/src/builder.rs +++ b/tracing-appender/src/builder.rs @@ -22,7 +22,22 @@ pub struct RollingFileAppenderBuilder { } impl RollingFileAppenderBuilder { - /// Creates an instance of RollingFileAppnderBuilder + /// Creates a new `RollingFileAppnderBuilder` + /// + /// It was introduced to open up the possibility to use `compression` without + /// breaking the current interface. + /// + /// Note that `compression` module is enabled by using an optional feature flag `compression` + /// + /// # Examples + /// ```rust + /// use tracing_appender::builder::RollingFileAppenderBuilder; + /// use tracing_appender::compression::CompressionOption; + /// use tracing_appender::rolling::Rotation; + /// let builder = RollingFileAppenderBuilder::new("/var/tmp", "my-app") + /// .rotation(Rotation::DAILY) + /// .compression(CompressionOption::GzipFast); + /// ``` pub fn new(log_directory: impl AsRef, log_filename_prefix: impl AsRef) -> Self { let log_directory = log_directory .as_ref() diff --git a/tracing-appender/src/compression.rs b/tracing-appender/src/compression.rs index 6bcfe23082..e62da9a13b 100644 --- a/tracing-appender/src/compression.rs +++ b/tracing-appender/src/compression.rs @@ -27,6 +27,7 @@ pub(crate) enum GzipCompressionLevel { Numerical(GzipCompressionLevelNumerical), } +/// Defines a conversion between `CompressionOption` and `flate2::Compression` impl Into for GzipCompressionLevel { fn into(self) -> Compression { match self { @@ -74,7 +75,22 @@ impl CompressionConfig { } } -#[derive(Debug)] +/// Defines a compression level for gzip algorithm. +/// +/// Compression levels are defined as they are in `flate2` crate where +/// - compression level 0 (`CompressionOption::GzipNone` or `CompressionOption::GzipLevel0`) +/// - compression level 1 (`CompressionOption::GzipFast` or `CompressionOption::GzipLevel1`) +/// - compression level n (where n is between 2 and 9) +/// - compression level 9 (`CompressionOption::GzipBest` or `CompressionOption::GzipLevel9`) +/// +/// ```rust +/// # fn docs() { +/// use tracing_appender::compression::CompressionOption; +/// let compression_level = CompressionOption::GzipBest; +/// # } +/// ``` +#[derive(Debug, Clone, Eq, PartialEq)] +#[non_exhaustive] pub enum CompressionOption { GzipNone, GzipFast, From 4a470c382dc1f5f0394d365ab216fbbc16fa3363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Mon, 27 Dec 2021 15:28:53 +0100 Subject: [PATCH 12/22] Rename feature flag compression to compression_gzip --- tracing-appender/Cargo.toml | 2 +- tracing-appender/src/builder.rs | 30 +++++++++++++++++++---------- tracing-appender/src/compression.rs | 10 +++++----- tracing-appender/src/lib.rs | 2 +- tracing-appender/src/rolling.rs | 8 ++++---- tracing-appender/src/writer.rs | 22 ++++++++++----------- 6 files changed, 42 insertions(+), 32 deletions(-) diff --git a/tracing-appender/Cargo.toml b/tracing-appender/Cargo.toml index 4579997d37..2d733a7bd6 100644 --- a/tracing-appender/Cargo.toml +++ b/tracing-appender/Cargo.toml @@ -21,7 +21,7 @@ edition = "2018" rust-version = "1.51.0" [features] -compression = ["flate2"] +compression_gzip = ["flate2"] [dependencies] crossbeam-channel = "0.5.0" diff --git a/tracing-appender/src/builder.rs b/tracing-appender/src/builder.rs index 344a7d11f4..20ab49e88d 100644 --- a/tracing-appender/src/builder.rs +++ b/tracing-appender/src/builder.rs @@ -1,23 +1,31 @@ +//! Builder struct for `RollingFileAppender` +//! +//! Gives access to setting additional options which are not avaible using standard interface. +//! Currently it is the only way to enable compression of logs. use crate::rolling::{create_writer_file, Inner, RollingFileAppender, Rotation}; use crate::sync::RwLock; use std::path::Path; use std::sync::atomic::AtomicUsize; use time::OffsetDateTime; -#[cfg(feature = "compression")] +#[cfg(feature = "compression_gzip")] use crate::compression::CompressionConfig; -#[cfg(feature = "compression")] +#[cfg(feature = "compression_gzip")] use crate::compression::CompressionOption; use crate::writer::WriterChannel; -#[derive(Debug)] +/// Struct for keeping temporary values of `RollingFileAppender`. +/// +/// Note that `log_directory` and `log_filename_prefix` are obligatory parameters and should +/// be passed into the constructor of `RollingFileAppenderBuilder`. +#[derive(Debug, Clone, Eq, PartialEq)] pub struct RollingFileAppenderBuilder { log_directory: String, log_filename_prefix: String, rotation: Option, - #[cfg(feature = "compression")] + #[cfg(feature = "compression_gzip")] compression: Option, } @@ -27,7 +35,8 @@ impl RollingFileAppenderBuilder { /// It was introduced to open up the possibility to use `compression` without /// breaking the current interface. /// - /// Note that `compression` module is enabled by using an optional feature flag `compression` + /// Note that `compression` module is enabled by using an optional feature flag + /// `compression_gzip` (for gzip algorithm) /// /// # Examples /// ```rust @@ -53,8 +62,8 @@ impl RollingFileAppenderBuilder { log_directory, log_filename_prefix, rotation: None, - #[cfg(feature = "compression")] - #[cfg_attr(docsrs, doc(cfg(feature = "compression")))] + #[cfg(feature = "compression_gzip")] + #[cfg_attr(docsrs, doc(cfg(feature = "compression_gzip")))] compression: None, } } @@ -65,13 +74,14 @@ impl RollingFileAppenderBuilder { self } - #[cfg(feature = "compression")] - #[cfg_attr(docsrs, doc(cfg(feature = "compression")))] + #[cfg(feature = "compression_gzip")] + #[cfg_attr(docsrs, doc(cfg(feature = "compression_gzip")))] pub fn compression(mut self, compression: CompressionOption) -> Self { self.compression = Some(compression.into()); self } + /// Builds an instance of `RollingFileAppender` using previously defined attributes. pub fn build(self) -> RollingFileAppender { let now = OffsetDateTime::now_utc(); let rotation = self.rotation.unwrap_or(Rotation::NEVER); @@ -95,7 +105,7 @@ impl RollingFileAppenderBuilder { log_filename_prefix: self.log_filename_prefix, next_date, rotation: rotation, - #[cfg(feature = "compression")] + #[cfg(feature = "compression_gzip")] compression: self.compression, }, writer, diff --git a/tracing-appender/src/compression.rs b/tracing-appender/src/compression.rs index e62da9a13b..3d64691623 100644 --- a/tracing-appender/src/compression.rs +++ b/tracing-appender/src/compression.rs @@ -1,13 +1,13 @@ use flate2::Compression; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub(crate) enum GzipCompressionLevelLiteral { None, Fast, Best, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub(crate) enum GzipCompressionLevelNumerical { Level0, Level1, @@ -21,7 +21,7 @@ pub(crate) enum GzipCompressionLevelNumerical { Level9, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub(crate) enum GzipCompressionLevel { Literal(GzipCompressionLevelLiteral), Numerical(GzipCompressionLevelNumerical), @@ -52,13 +52,13 @@ impl Into for GzipCompressionLevel { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub(crate) struct GzipCompression { pub(crate) level: GzipCompressionLevel, } /// Data structure to pass compression parameters -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] #[non_exhaustive] pub(crate) enum CompressionConfig { Gzip(GzipCompression), diff --git a/tracing-appender/src/lib.rs b/tracing-appender/src/lib.rs index ae7ecb06f9..dbd24ce20e 100644 --- a/tracing-appender/src/lib.rs +++ b/tracing-appender/src/lib.rs @@ -163,7 +163,7 @@ pub(crate) mod sync; mod writer; -#[cfg(feature = "compression")] +#[cfg(feature = "compression_gzip")] mod compression; pub mod builder; diff --git a/tracing-appender/src/rolling.rs b/tracing-appender/src/rolling.rs index a91bbc10a3..6b268afdd5 100644 --- a/tracing-appender/src/rolling.rs +++ b/tracing-appender/src/rolling.rs @@ -27,7 +27,7 @@ //! # } //! ``` use crate::builder::RollingFileAppenderBuilder; -#[cfg(feature = "compression")] +#[cfg(feature = "compression_gzip")] use crate::compression::CompressionConfig; use crate::sync::{RwLock, RwLockReadGuard}; use crate::writer::WriterChannel; @@ -107,7 +107,7 @@ pub(crate) struct Inner { pub(crate) log_filename_prefix: String, pub(crate) rotation: Rotation, pub(crate) next_date: AtomicUsize, - #[cfg(feature = "compression")] + #[cfg(feature = "compression_gzip")] pub(crate) compression: Option, } @@ -477,7 +477,7 @@ impl io::Write for RollingWriter<'_> { // === impl Inner === impl Inner { - #[cfg(feature = "compression")] + #[cfg(feature = "compression_gzip")] fn refresh_writer(&self, now: OffsetDateTime, file: &mut WriterChannel) { debug_assert!(self.should_rollover(now)); @@ -494,7 +494,7 @@ impl Inner { Self::refresh_writer_channel(file, writer); } - #[cfg(not(feature = "compression"))] + #[cfg(not(feature = "compression_gzip"))] fn refresh_writer(&self, now: OffsetDateTime, file: &mut WriterChannel) { debug_assert!(self.should_rollover(now)); diff --git a/tracing-appender/src/writer.rs b/tracing-appender/src/writer.rs index 100741a859..a586f08a98 100644 --- a/tracing-appender/src/writer.rs +++ b/tracing-appender/src/writer.rs @@ -2,7 +2,7 @@ use crate::rolling::create_writer_file; use std::fs::File; use std::io; -#[cfg(feature = "compression")] +#[cfg(feature = "compression_gzip")] use { crate::compression::CompressionConfig, flate2::write::GzEncoder, @@ -10,7 +10,7 @@ use { std::sync::{Arc, RwLock}, }; -#[cfg(feature = "compression")] +#[cfg(feature = "compression_gzip")] #[derive(Debug)] pub(crate) struct CompressedGzip { compression: CompressionConfig, @@ -20,16 +20,16 @@ pub(crate) struct CompressedGzip { #[derive(Debug)] pub(crate) enum WriterChannel { File(File), - #[cfg(feature = "compression")] + #[cfg(feature = "compression_gzip")] CompressedFileGzip(CompressedGzip), } impl WriterChannel { - #[cfg(feature = "compression")] + #[cfg(feature = "compression_gzip")] pub(crate) fn new( directory: &str, filename: &str, - #[cfg(feature = "compression")] compression: Option, + #[cfg(feature = "compression_gzip")] compression: Option, ) -> io::Result { if let Some(compression) = compression { Self::new_with_compression(directory, filename, compression) @@ -38,7 +38,7 @@ impl WriterChannel { } } - #[cfg(not(feature = "compression"))] + #[cfg(not(feature = "compression_gzip"))] pub(crate) fn new(directory: &str, filename: &str) -> io::Result { Self::new_without_compression(directory, filename) } @@ -48,7 +48,7 @@ impl WriterChannel { Ok(WriterChannel::File(file)) } - #[cfg(feature = "compression")] + #[cfg(feature = "compression_gzip")] pub(crate) fn new_with_compression( directory: &str, filename: &str, @@ -70,7 +70,7 @@ impl io::Write for WriterChannel { fn write(&mut self, buf: &[u8]) -> io::Result { match self { WriterChannel::File(f) => f.write(buf), - #[cfg(feature = "compression")] + #[cfg(feature = "compression_gzip")] WriterChannel::CompressedFileGzip(gz) => { let mut buffer = gz.buffer.write().unwrap(); buffer.write(buf) @@ -81,7 +81,7 @@ impl io::Write for WriterChannel { fn flush(&mut self) -> io::Result<()> { match self { WriterChannel::File(f) => f.flush(), - #[cfg(feature = "compression")] + #[cfg(feature = "compression_gzip")] WriterChannel::CompressedFileGzip(gz) => { let mut buffer = gz.buffer.write().unwrap(); buffer.flush() @@ -94,7 +94,7 @@ impl io::Write for &WriterChannel { fn write(&mut self, buf: &[u8]) -> io::Result { match self { WriterChannel::File(f) => (&*f).write(buf), - #[cfg(feature = "compression")] + #[cfg(feature = "compression_gzip")] WriterChannel::CompressedFileGzip(gz) => { let mut buffer = gz.buffer.write().unwrap(); buffer.write(buf) @@ -105,7 +105,7 @@ impl io::Write for &WriterChannel { fn flush(&mut self) -> io::Result<()> { match self { WriterChannel::File(f) => (&*f).flush(), - #[cfg(feature = "compression")] + #[cfg(feature = "compression_gzip")] WriterChannel::CompressedFileGzip(gz) => { let mut buffer = gz.buffer.write().unwrap(); buffer.flush() From 241ea8f7111e54925952c153de1acc1ce47c282c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Tue, 28 Dec 2021 11:41:43 +0100 Subject: [PATCH 13/22] PR changes --- tracing-appender/src/lib.rs | 5 -- tracing-appender/src/{ => rolling}/builder.rs | 8 +-- .../src/{ => rolling}/compression.rs | 51 ++++++++++--------- .../src/{rolling.rs => rolling/mod.rs} | 42 ++++++--------- tracing-appender/src/writer.rs | 20 ++++---- 5 files changed, 57 insertions(+), 69 deletions(-) rename tracing-appender/src/{ => rolling}/builder.rs (96%) rename tracing-appender/src/{ => rolling}/compression.rs (83%) rename tracing-appender/src/{rolling.rs => rolling/mod.rs} (95%) diff --git a/tracing-appender/src/lib.rs b/tracing-appender/src/lib.rs index dbd24ce20e..a3ccd5ff29 100644 --- a/tracing-appender/src/lib.rs +++ b/tracing-appender/src/lib.rs @@ -163,11 +163,6 @@ pub(crate) mod sync; mod writer; -#[cfg(feature = "compression_gzip")] -mod compression; - -pub mod builder; - /// Convenience function for creating a non-blocking, off-thread writer. /// /// See the [`non_blocking` module's docs][mod@non_blocking]'s for more details. diff --git a/tracing-appender/src/builder.rs b/tracing-appender/src/rolling/builder.rs similarity index 96% rename from tracing-appender/src/builder.rs rename to tracing-appender/src/rolling/builder.rs index 20ab49e88d..dcf361a5fa 100644 --- a/tracing-appender/src/builder.rs +++ b/tracing-appender/src/rolling/builder.rs @@ -9,10 +9,9 @@ use std::sync::atomic::AtomicUsize; use time::OffsetDateTime; #[cfg(feature = "compression_gzip")] -use crate::compression::CompressionConfig; - -#[cfg(feature = "compression_gzip")] -use crate::compression::CompressionOption; +use { + crate::rolling::compression::CompressionConfig, crate::rolling::compression::CompressionOption, +}; use crate::writer::WriterChannel; @@ -74,6 +73,7 @@ impl RollingFileAppenderBuilder { self } + /// Sets compression level #[cfg(feature = "compression_gzip")] #[cfg_attr(docsrs, doc(cfg(feature = "compression_gzip")))] pub fn compression(mut self, compression: CompressionOption) -> Self { diff --git a/tracing-appender/src/compression.rs b/tracing-appender/src/rolling/compression.rs similarity index 83% rename from tracing-appender/src/compression.rs rename to tracing-appender/src/rolling/compression.rs index 3d64691623..6289977afb 100644 --- a/tracing-appender/src/compression.rs +++ b/tracing-appender/src/rolling/compression.rs @@ -1,3 +1,6 @@ +//! Defines configuration for passing compression options +//! +//! Currently only gzip compression is implemented. use flate2::Compression; #[derive(Debug, Clone, Eq, PartialEq)] @@ -8,17 +11,18 @@ pub(crate) enum GzipCompressionLevelLiteral { } #[derive(Debug, Clone, Eq, PartialEq)] +#[repr(u32)] pub(crate) enum GzipCompressionLevelNumerical { - Level0, - Level1, - Level2, - Level3, - Level4, - Level5, - Level6, - Level7, - Level8, - Level9, + Level0 = 0, + Level1 = 1, + Level2 = 2, + Level3 = 3, + Level4 = 4, + Level5 = 5, + Level6 = 6, + Level7 = 7, + Level8 = 8, + Level9 = 9, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -36,18 +40,7 @@ impl Into for GzipCompressionLevel { GzipCompressionLevelLiteral::Fast => Compression::fast(), GzipCompressionLevelLiteral::Best => Compression::best(), }, - GzipCompressionLevel::Numerical(num) => match num { - GzipCompressionLevelNumerical::Level0 => Compression::new(0), - GzipCompressionLevelNumerical::Level1 => Compression::new(1), - GzipCompressionLevelNumerical::Level2 => Compression::new(2), - GzipCompressionLevelNumerical::Level3 => Compression::new(3), - GzipCompressionLevelNumerical::Level4 => Compression::new(4), - GzipCompressionLevelNumerical::Level5 => Compression::new(5), - GzipCompressionLevelNumerical::Level6 => Compression::new(6), - GzipCompressionLevelNumerical::Level7 => Compression::new(7), - GzipCompressionLevelNumerical::Level8 => Compression::new(8), - GzipCompressionLevelNumerical::Level9 => Compression::new(9), - }, + GzipCompressionLevel::Numerical(num) => Compression::new(num as u32), } } } @@ -59,7 +52,6 @@ pub(crate) struct GzipCompression { /// Data structure to pass compression parameters #[derive(Debug, Clone, Eq, PartialEq)] -#[non_exhaustive] pub(crate) enum CompressionConfig { Gzip(GzipCompression), } @@ -92,18 +84,31 @@ impl CompressionConfig { #[derive(Debug, Clone, Eq, PartialEq)] #[non_exhaustive] pub enum CompressionOption { + /// No compression (gzip compression level 0) GzipNone, + /// Fast compression (gzip compression level 1) GzipFast, + /// Fast compression (gzip compression level 9) GzipBest, + /// Gzip compression level 0 GzipLevel0, + /// Gzip compression level 1 GzipLevel1, + /// Gzip compression level 2 GzipLevel2, + /// Gzip compression level 3 GzipLevel3, + /// Gzip compression level 4 GzipLevel4, + /// Gzip compression level 5 GzipLevel5, + /// Gzip compression level 6 GzipLevel6, + /// Gzip compression level 7 GzipLevel7, + /// Gzip compression level 8 GzipLevel8, + /// Gzip compression level 9 GzipLevel9, } diff --git a/tracing-appender/src/rolling.rs b/tracing-appender/src/rolling/mod.rs similarity index 95% rename from tracing-appender/src/rolling.rs rename to tracing-appender/src/rolling/mod.rs index 6b268afdd5..3596e0b342 100644 --- a/tracing-appender/src/rolling.rs +++ b/tracing-appender/src/rolling/mod.rs @@ -26,9 +26,10 @@ //! let file_appender = RollingFileAppender::new(Rotation::HOURLY, "/some/directory", "prefix.log"); //! # } //! ``` -use crate::builder::RollingFileAppenderBuilder; +mod builder; +pub use crate::rolling::builder::RollingFileAppenderBuilder; #[cfg(feature = "compression_gzip")] -use crate::compression::CompressionConfig; +use crate::rolling::compression::CompressionConfig; use crate::sync::{RwLock, RwLockReadGuard}; use crate::writer::WriterChannel; use std::{ @@ -40,6 +41,9 @@ use std::{ }; use time::{format_description, Duration, OffsetDateTime, Time}; +#[cfg(feature = "compression_gzip")] +pub mod compression; + /// A file appender with the ability to rotate log files at a fixed schedule. /// /// `RollingFileAppender` implements the [`std:io::Write` trait][write] and will @@ -103,12 +107,12 @@ pub struct RollingWriter<'a>(RwLockReadGuard<'a, WriterChannel>); #[derive(Debug)] pub(crate) struct Inner { - pub(crate) log_directory: String, - pub(crate) log_filename_prefix: String, - pub(crate) rotation: Rotation, - pub(crate) next_date: AtomicUsize, + log_directory: String, + log_filename_prefix: String, + rotation: Rotation, + next_date: AtomicUsize, #[cfg(feature = "compression_gzip")] - pub(crate) compression: Option, + compression: Option, } // === impl RollingFileAppender === @@ -477,7 +481,6 @@ impl io::Write for RollingWriter<'_> { // === impl Inner === impl Inner { - #[cfg(feature = "compression_gzip")] fn refresh_writer(&self, now: OffsetDateTime, file: &mut WriterChannel) { debug_assert!(self.should_rollover(now)); @@ -485,26 +488,13 @@ impl Inner { .rotation .join_date(&self.log_filename_prefix, &now, false); - let writer = if let Some(compression) = self.compression.clone() { - WriterChannel::new_with_compression(&self.log_directory, &filename, compression) - } else { - WriterChannel::new_without_compression(&self.log_directory, &filename) - }; + #[cfg(feature = "compression_gzip")] + let writer = WriterChannel::new(&self.log_directory, &filename, self.compression.clone()); - Self::refresh_writer_channel(file, writer); - } + #[cfg(not(feature = "compression_gzip"))] + let writer = WriterChannel::new(&self.log_directory, &filename); - #[cfg(not(feature = "compression_gzip"))] - fn refresh_writer(&self, now: OffsetDateTime, file: &mut WriterChannel) { - debug_assert!(self.should_rollover(now)); - - let filename = self - .rotation - .join_date(&self.log_filename_prefix, &now, false); - - let writer = WriterChannel::new_without_compression(&self.log_directory, &filename); - - Self::refresh_writer_channel(file, writer) + Self::refresh_writer_channel(file, writer); } fn refresh_writer_channel(file: &mut WriterChannel, writer: io::Result) { diff --git a/tracing-appender/src/writer.rs b/tracing-appender/src/writer.rs index a586f08a98..da303b1fb7 100644 --- a/tracing-appender/src/writer.rs +++ b/tracing-appender/src/writer.rs @@ -4,17 +4,15 @@ use std::io; #[cfg(feature = "compression_gzip")] use { - crate::compression::CompressionConfig, - flate2::write::GzEncoder, - std::io::BufWriter, - std::sync::{Arc, RwLock}, + crate::rolling::compression::CompressionConfig, flate2::write::GzEncoder, std::io::BufWriter, + std::sync::Mutex, }; #[cfg(feature = "compression_gzip")] #[derive(Debug)] pub(crate) struct CompressedGzip { compression: CompressionConfig, - buffer: Arc>>>>, + buffer: Mutex>>>, } #[derive(Debug)] @@ -29,7 +27,7 @@ impl WriterChannel { pub(crate) fn new( directory: &str, filename: &str, - #[cfg(feature = "compression_gzip")] compression: Option, + compression: Option, ) -> io::Result { if let Some(compression) = compression { Self::new_with_compression(directory, filename, compression) @@ -60,7 +58,7 @@ impl WriterChannel { let writer = BufWriter::new(gzfile); let compressed_gz = CompressedGzip { compression: compression.clone(), - buffer: Arc::new(RwLock::new(writer)), + buffer: Mutex::new(writer), }; Ok(WriterChannel::CompressedFileGzip(compressed_gz)) } @@ -72,7 +70,7 @@ impl io::Write for WriterChannel { WriterChannel::File(f) => f.write(buf), #[cfg(feature = "compression_gzip")] WriterChannel::CompressedFileGzip(gz) => { - let mut buffer = gz.buffer.write().unwrap(); + let mut buffer = gz.buffer.lock().unwrap(); buffer.write(buf) } } @@ -83,7 +81,7 @@ impl io::Write for WriterChannel { WriterChannel::File(f) => f.flush(), #[cfg(feature = "compression_gzip")] WriterChannel::CompressedFileGzip(gz) => { - let mut buffer = gz.buffer.write().unwrap(); + let mut buffer = gz.buffer.lock().unwrap(); buffer.flush() } } @@ -96,7 +94,7 @@ impl io::Write for &WriterChannel { WriterChannel::File(f) => (&*f).write(buf), #[cfg(feature = "compression_gzip")] WriterChannel::CompressedFileGzip(gz) => { - let mut buffer = gz.buffer.write().unwrap(); + let mut buffer = gz.buffer.lock().unwrap(); buffer.write(buf) } } @@ -107,7 +105,7 @@ impl io::Write for &WriterChannel { WriterChannel::File(f) => (&*f).flush(), #[cfg(feature = "compression_gzip")] WriterChannel::CompressedFileGzip(gz) => { - let mut buffer = gz.buffer.write().unwrap(); + let mut buffer = gz.buffer.lock().unwrap(); buffer.flush() } } From 5d696b674e4eec6c599b09f5a5b5fbfd00d23e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Mon, 3 Jan 2022 10:17:38 +0100 Subject: [PATCH 14/22] Clean up file extension --- tracing-appender/src/rolling/builder.rs | 47 ++++++++++++++++++--- tracing-appender/src/rolling/compression.rs | 13 ++++++ tracing-appender/src/rolling/mod.rs | 46 ++++++++++---------- tracing-appender/src/writer.rs | 8 ++++ 4 files changed, 84 insertions(+), 30 deletions(-) diff --git a/tracing-appender/src/rolling/builder.rs b/tracing-appender/src/rolling/builder.rs index dcf361a5fa..270ef80bdd 100644 --- a/tracing-appender/src/rolling/builder.rs +++ b/tracing-appender/src/rolling/builder.rs @@ -81,17 +81,42 @@ impl RollingFileAppenderBuilder { self } + pub(crate) fn get_extension(&self) -> Option { + #[cfg(feature = "compression_gzip")] + if let Some(compression) = self.compression.clone() { + compression.extension().map(|v| v.to_string()) + } else { + None + } + + #[cfg(not(feature = "compression_gzip"))] + None + } + /// Builds an instance of `RollingFileAppender` using previously defined attributes. pub fn build(self) -> RollingFileAppender { let now = OffsetDateTime::now_utc(); - let rotation = self.rotation.unwrap_or(Rotation::NEVER); - let filename = rotation.join_date(self.log_filename_prefix.as_str(), &now, false); + let rotation = self.rotation.clone().unwrap_or(Rotation::NEVER).clone(); + let extension = self.get_extension(); + let filename = rotation.join_date(self.log_filename_prefix.as_str(), &now, extension); let next_date = rotation.next_date(&now); - let writer = RwLock::new(WriterChannel::File( - create_writer_file(self.log_directory.as_str(), &filename) - .expect("failed to create appender"), - )); + #[cfg(not(feature = "compression_gzip"))] + let writer = self.create_file_writer(filename.as_str()); + + #[cfg(feature = "compression_gzip")] + let writer = if let Some(compression) = self.compression.clone() { + RwLock::new( + WriterChannel::new_with_compression( + self.log_directory.as_str(), + &filename, + compression, + ) + .unwrap(), + ) + } else { + self.create_file_writer(filename.as_str()) + }; let next_date = AtomicUsize::new( next_date @@ -104,11 +129,19 @@ impl RollingFileAppenderBuilder { log_directory: self.log_directory, log_filename_prefix: self.log_filename_prefix, next_date, - rotation: rotation, + rotation: rotation.clone(), #[cfg(feature = "compression_gzip")] compression: self.compression, }, writer, } } + + fn create_file_writer(&self, filename: &str) -> RwLock { + let a = RwLock::new(WriterChannel::File( + create_writer_file(self.log_directory.as_str(), &filename) + .expect("failed to create appender"), + )); + a + } } diff --git a/tracing-appender/src/rolling/compression.rs b/tracing-appender/src/rolling/compression.rs index 6289977afb..bffcc8915c 100644 --- a/tracing-appender/src/rolling/compression.rs +++ b/tracing-appender/src/rolling/compression.rs @@ -65,6 +65,12 @@ impl CompressionConfig { } } } + + pub(crate) fn extension(&self) -> Option<&str> { + match self { + CompressionConfig::Gzip(_) => Some("gz"), + } + } } /// Defines a compression level for gzip algorithm. @@ -157,3 +163,10 @@ impl Into for CompressionOption { } } } + +#[cfg(test)] +mod test { + + #[test] + fn test_compression() {} +} diff --git a/tracing-appender/src/rolling/mod.rs b/tracing-appender/src/rolling/mod.rs index 3596e0b342..82cfb02d78 100644 --- a/tracing-appender/src/rolling/mod.rs +++ b/tracing-appender/src/rolling/mod.rs @@ -418,7 +418,7 @@ impl Rotation { &self, filename: &str, date: &OffsetDateTime, - compress: bool, + extension: Option, ) -> String { match *self { Rotation::MINUTELY => { @@ -428,7 +428,7 @@ impl Rotation { let date = date .format(&format) .expect("Unable to format OffsetDateTime; this is a bug in tracing-appender"); - Rotation::format_params(filename, compress, date) + Rotation::format_params(filename, extension, date) } Rotation::HOURLY => { let format = format_description::parse("[year]-[month]-[day]-[hour]") @@ -437,7 +437,7 @@ impl Rotation { let date = date .format(&format) .expect("Unable to format OffsetDateTime; this is a bug in tracing-appender"); - Rotation::format_params(filename, compress, date) + Rotation::format_params(filename, extension, date) } Rotation::DAILY => { let format = format_description::parse("[year]-[month]-[day]") @@ -445,11 +445,11 @@ impl Rotation { let date = date .format(&format) .expect("Unable to format OffsetDateTime; this is a bug in tracing-appender"); - Rotation::format_params(filename, compress, date) + Rotation::format_params(filename, extension, date) } Rotation::NEVER => { - if compress { - format!("{}.gz", filename.to_string()) + if let Some(extension) = extension { + format!("{}.{}", filename.to_string(), extension) } else { filename.to_string() } @@ -457,9 +457,9 @@ impl Rotation { } } - fn format_params(filename: &str, compress: bool, date: String) -> String { - if compress { - format!("{}.{}.gz", filename, date) + fn format_params(filename: &str, extension: Option, date: String) -> String { + if let Some(extension) = extension { + format!("{}.{}.{}", filename, date, extension) } else { format!("{}.{}", filename, date) } @@ -486,7 +486,7 @@ impl Inner { let filename = self .rotation - .join_date(&self.log_filename_prefix, &now, false); + .join_date(&self.log_filename_prefix, &now, None); #[cfg(feature = "compression_gzip")] let writer = WriterChannel::new(&self.log_directory, &filename, self.compression.clone()); @@ -579,7 +579,7 @@ mod test { appender.flush().expect("Failed to flush!"); } - fn test_appender(rotation: Rotation, file_prefix: &str, compress: bool) { + fn test_appender(rotation: Rotation, file_prefix: &str) { let directory = tempfile::tempdir().expect("failed to create tempdir"); let mut appender = RollingFileAppender::new(rotation, directory.path(), file_prefix); @@ -594,22 +594,22 @@ mod test { #[test] fn write_minutely_log() { - test_appender(Rotation::HOURLY, "minutely.log", false); + test_appender(Rotation::HOURLY, "minutely.log"); } #[test] fn write_hourly_log() { - test_appender(Rotation::HOURLY, "hourly.log", false); + test_appender(Rotation::HOURLY, "hourly.log"); } #[test] fn write_daily_log() { - test_appender(Rotation::DAILY, "daily.log", false); + test_appender(Rotation::DAILY, "daily.log"); } #[test] fn write_never_log() { - test_appender(Rotation::NEVER, "never.log", false); + test_appender(Rotation::NEVER, "never.log"); } #[test] @@ -655,35 +655,35 @@ mod test { let now = OffsetDateTime::parse("2020-02-01 10:01:00 +00:00:00", &format).unwrap(); // per-minute - let path = Rotation::MINUTELY.join_date("app.log", &now, false); + let path = Rotation::MINUTELY.join_date("app.log", &now, None); assert_eq!("app.log.2020-02-01-10-01", path); // per-hour - let path = Rotation::HOURLY.join_date("app.log", &now, false); + let path = Rotation::HOURLY.join_date("app.log", &now, None); assert_eq!("app.log.2020-02-01-10", path); // per-day - let path = Rotation::DAILY.join_date("app.log", &now, false); + let path = Rotation::DAILY.join_date("app.log", &now, None); assert_eq!("app.log.2020-02-01", path); // never - let path = Rotation::NEVER.join_date("app.log", &now, false); + let path = Rotation::NEVER.join_date("app.log", &now, None); assert_eq!("app.log", path); // per-minute compressed - let path = Rotation::MINUTELY.join_date("app.log", &now, true); + let path = Rotation::MINUTELY.join_date("app.log", &now, Some("gz")); assert_eq!("app.log.2020-02-01-10-01.gz", path); // per-hour compressed - let path = Rotation::HOURLY.join_date("app.log", &now, true); + let path = Rotation::HOURLY.join_date("app.log", &now, Some("gz")); assert_eq!("app.log.2020-02-01-10.gz", path); // per-day compressed - let path = Rotation::DAILY.join_date("app.log", &now, true); + let path = Rotation::DAILY.join_date("app.log", &now, Some("gz")); assert_eq!("app.log.2020-02-01.gz", path); // never compressed - let path = Rotation::NEVER.join_date("app.log", &now, true); + let path = Rotation::NEVER.join_date("app.log", &now, Some("gz")); assert_eq!("app.log.gz", path) } } diff --git a/tracing-appender/src/writer.rs b/tracing-appender/src/writer.rs index da303b1fb7..c50c0745ef 100644 --- a/tracing-appender/src/writer.rs +++ b/tracing-appender/src/writer.rs @@ -62,6 +62,14 @@ impl WriterChannel { }; Ok(WriterChannel::CompressedFileGzip(compressed_gz)) } + + pub(crate) fn extension(self) -> Option { + match self { + WriterChannel::File(_) => None, + #[cfg(feature = "compression_gzip")] + WriterChannel::CompressedFileGzip(_) => Some("gz".to_string()), + } + } } impl io::Write for WriterChannel { From 0bc8b537c7d6f54474a04d8d37af7c44def97932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Mon, 21 Feb 2022 21:34:22 +0100 Subject: [PATCH 15/22] Add tests --- tracing-appender/src/rolling/builder.rs | 20 +++++----- tracing-appender/src/rolling/compression.rs | 44 ++++++++++++++++++++- tracing-appender/src/rolling/mod.rs | 18 ++++----- tracing-appender/src/writer.rs | 2 + 4 files changed, 65 insertions(+), 19 deletions(-) diff --git a/tracing-appender/src/rolling/builder.rs b/tracing-appender/src/rolling/builder.rs index 270ef80bdd..273f5aab21 100644 --- a/tracing-appender/src/rolling/builder.rs +++ b/tracing-appender/src/rolling/builder.rs @@ -37,15 +37,17 @@ impl RollingFileAppenderBuilder { /// Note that `compression` module is enabled by using an optional feature flag /// `compression_gzip` (for gzip algorithm) /// - /// # Examples - /// ```rust - /// use tracing_appender::builder::RollingFileAppenderBuilder; - /// use tracing_appender::compression::CompressionOption; - /// use tracing_appender::rolling::Rotation; - /// let builder = RollingFileAppenderBuilder::new("/var/tmp", "my-app") - /// .rotation(Rotation::DAILY) - /// .compression(CompressionOption::GzipFast); - /// ``` + // # Examples + // ```rust + // # #[cfg(feature = "gzip_compression")] { + // use tracing_appender::builder::RollingFileAppenderBuilder; + // use tracing_appender::compression::CompressionOption; + // use tracing_appender::rolling::Rotation; + // let builder = RollingFileAppenderBuilder::new("/var/tmp", "my-app") + // .rotation(Rotation::DAILY) + // .compression(CompressionOption::GzipFast); + // # } + // ``` pub fn new(log_directory: impl AsRef, log_filename_prefix: impl AsRef) -> Self { let log_directory = log_directory .as_ref() diff --git a/tracing-appender/src/rolling/compression.rs b/tracing-appender/src/rolling/compression.rs index bffcc8915c..9097e283f2 100644 --- a/tracing-appender/src/rolling/compression.rs +++ b/tracing-appender/src/rolling/compression.rs @@ -66,6 +66,7 @@ impl CompressionConfig { } } + #[allow(unused)] pub(crate) fn extension(&self) -> Option<&str> { match self { CompressionConfig::Gzip(_) => Some("gz"), @@ -82,10 +83,12 @@ impl CompressionConfig { /// - compression level 9 (`CompressionOption::GzipBest` or `CompressionOption::GzipLevel9`) /// /// ```rust +/// # #[cfg(feature = "gzip_compression")] { /// # fn docs() { /// use tracing_appender::compression::CompressionOption; /// let compression_level = CompressionOption::GzipBest; /// # } +/// # } /// ``` #[derive(Debug, Clone, Eq, PartialEq)] #[non_exhaustive] @@ -166,7 +169,46 @@ impl Into for CompressionOption { #[cfg(test)] mod test { + use crate::rolling::compression::CompressionOption; + use crate::rolling::test::write_to_log; + use crate::rolling::{RollingFileAppenderBuilder, Rotation}; + use flate2::read::GzDecoder; + use std::fs; + use std::io::Read; + use std::path::Path; + + fn find_str_in_compressed_log(dir_path: &Path, expected_value: &str) -> bool { + let dir_contents = fs::read_dir(dir_path).expect("Failed to read directory"); + + for entry in dir_contents { + let path = entry.expect("Expected dir entry").path(); + let bytes = fs::read(&path).expect("Cannot read bytes from compressed log"); + let mut decoder = GzDecoder::new(&bytes[..]); + let mut s = String::new(); + let _ = decoder.read_to_string(&mut s); + if s.as_str() == expected_value { + return true; + } + } + + false + } #[test] - fn test_compression() {} + fn test_compressed_appender() { + let file_prefix = "my-app-compressed-log"; + let directory = tempfile::tempdir().expect("failed to create tempdir"); + let mut appender = RollingFileAppenderBuilder::new(directory.path(), file_prefix) + .rotation(Rotation::DAILY) + .compression(CompressionOption::GzipFast) + .build(); + + let expected_value = "Hello"; + write_to_log(&mut appender, expected_value); + assert!(find_str_in_compressed_log(directory.path(), expected_value)); + + directory + .close() + .expect("Failed to explicitly close TempDir. TempDir should delete once out of scope.") + } } diff --git a/tracing-appender/src/rolling/mod.rs b/tracing-appender/src/rolling/mod.rs index d266681ea7..d3ed747d58 100644 --- a/tracing-appender/src/rolling/mod.rs +++ b/tracing-appender/src/rolling/mod.rs @@ -428,7 +428,7 @@ impl Rotation { let date = date .format(&format) .expect("Unable to format OffsetDateTime; this is a bug in tracing-appender"); - Rotation::format_params(filename, extension, date) + Rotation::format_params(filename, extension, date.as_str()) } Rotation::HOURLY => { let format = format_description::parse("[year]-[month]-[day]-[hour]") @@ -437,7 +437,7 @@ impl Rotation { let date = date .format(&format) .expect("Unable to format OffsetDateTime; this is a bug in tracing-appender"); - Rotation::format_params(filename, extension, date) + Rotation::format_params(filename, extension, date.as_str()) } Rotation::DAILY => { let format = format_description::parse("[year]-[month]-[day]") @@ -445,7 +445,7 @@ impl Rotation { let date = date .format(&format) .expect("Unable to format OffsetDateTime; this is a bug in tracing-appender"); - Rotation::format_params(filename, extension, date) + Rotation::format_params(filename, extension, date.as_str()) } Rotation::NEVER => { if let Some(extension) = extension { @@ -457,7 +457,7 @@ impl Rotation { } } - fn format_params(filename: &str, extension: Option, date: String) -> String { + fn format_params(filename: &str, extension: Option, date: &str) -> String { if let Some(extension) = extension { format!("{}.{}.{}", filename, date, extension) } else { @@ -572,7 +572,7 @@ mod test { false } - fn write_to_log(appender: &mut RollingFileAppender, msg: &str) { + pub(crate) fn write_to_log(appender: &mut RollingFileAppender, msg: &str) { appender .write_all(msg.as_bytes()) .expect("Failed to write to appender"); @@ -671,19 +671,19 @@ mod test { assert_eq!("app.log", path); // per-minute compressed - let path = Rotation::MINUTELY.join_date("app.log", &now, Some("gz")); + let path = Rotation::MINUTELY.join_date("app.log", &now, Some("gz".into())); assert_eq!("app.log.2020-02-01-10-01.gz", path); // per-hour compressed - let path = Rotation::HOURLY.join_date("app.log", &now, Some("gz")); + let path = Rotation::HOURLY.join_date("app.log", &now, Some("gz".into())); assert_eq!("app.log.2020-02-01-10.gz", path); // per-day compressed - let path = Rotation::DAILY.join_date("app.log", &now, Some("gz")); + let path = Rotation::DAILY.join_date("app.log", &now, Some("gz".into())); assert_eq!("app.log.2020-02-01.gz", path); // never compressed - let path = Rotation::NEVER.join_date("app.log", &now, Some("gz")); + let path = Rotation::NEVER.join_date("app.log", &now, Some("gz".into())); assert_eq!("app.log.gz", path) } } diff --git a/tracing-appender/src/writer.rs b/tracing-appender/src/writer.rs index c50c0745ef..994dd4d55d 100644 --- a/tracing-appender/src/writer.rs +++ b/tracing-appender/src/writer.rs @@ -11,6 +11,7 @@ use { #[cfg(feature = "compression_gzip")] #[derive(Debug)] pub(crate) struct CompressedGzip { + #[allow(unused)] compression: CompressionConfig, buffer: Mutex>>>, } @@ -63,6 +64,7 @@ impl WriterChannel { Ok(WriterChannel::CompressedFileGzip(compressed_gz)) } + #[allow(unused)] pub(crate) fn extension(self) -> Option { match self { WriterChannel::File(_) => None, From eb9803d18a323bcc20313776f1024d0b2d496463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Wed, 23 Feb 2022 14:11:20 +0100 Subject: [PATCH 16/22] Update tracing-appender/src/rolling/builder.rs Co-authored-by: Eliza Weisman --- tracing-appender/src/rolling/builder.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tracing-appender/src/rolling/builder.rs b/tracing-appender/src/rolling/builder.rs index 273f5aab21..6b5d424743 100644 --- a/tracing-appender/src/rolling/builder.rs +++ b/tracing-appender/src/rolling/builder.rs @@ -15,10 +15,9 @@ use { use crate::writer::WriterChannel; -/// Struct for keeping temporary values of `RollingFileAppender`. +/// A builder for configuring new [`RollingFileAppender`]s. /// -/// Note that `log_directory` and `log_filename_prefix` are obligatory parameters and should -/// be passed into the constructor of `RollingFileAppenderBuilder`. +/// This can be used to configure additional options, such as adding compression. #[derive(Debug, Clone, Eq, PartialEq)] pub struct RollingFileAppenderBuilder { log_directory: String, From a950404dba6ad1eef4c9bc26fa95d48d7642e386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Wed, 23 Feb 2022 14:14:42 +0100 Subject: [PATCH 17/22] Update tracing-appender/src/rolling/builder.rs Co-authored-by: Eliza Weisman --- tracing-appender/src/rolling/builder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tracing-appender/src/rolling/builder.rs b/tracing-appender/src/rolling/builder.rs index 6b5d424743..0560bf36b8 100644 --- a/tracing-appender/src/rolling/builder.rs +++ b/tracing-appender/src/rolling/builder.rs @@ -51,12 +51,12 @@ impl RollingFileAppenderBuilder { let log_directory = log_directory .as_ref() .to_str() - .expect("Cannot convert log_directory Path to str") + .expect("`log_directory` must not contain invalid UTF-8 characters") .to_string(); let log_filename_prefix = log_filename_prefix .as_ref() .to_str() - .expect("Cannot convert log_filename_prefix Path to str") + .expect("`log_directory` must not contain invalid UTF-8 characters") .to_string(); RollingFileAppenderBuilder { log_directory, From 1748b4ac9b0f80f8b6bc28ab195b1475be486a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Wed, 23 Feb 2022 14:15:02 +0100 Subject: [PATCH 18/22] Update tracing-appender/src/rolling/builder.rs Co-authored-by: Eliza Weisman --- tracing-appender/src/rolling/builder.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tracing-appender/src/rolling/builder.rs b/tracing-appender/src/rolling/builder.rs index 0560bf36b8..3957556187 100644 --- a/tracing-appender/src/rolling/builder.rs +++ b/tracing-appender/src/rolling/builder.rs @@ -68,7 +68,9 @@ impl RollingFileAppenderBuilder { } } - /// Sets Rotation + /// Configures when log files will be rotated. + /// + /// By default, no rotation will occur. pub fn rotation(mut self, rotation: Rotation) -> Self { self.rotation = Some(rotation); self From 85dbd742f66e5bb411426d207e4866e58845ac86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Wed, 23 Feb 2022 14:16:23 +0100 Subject: [PATCH 19/22] Apply suggestions from code review Co-authored-by: Eliza Weisman --- tracing-appender/src/rolling/builder.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tracing-appender/src/rolling/builder.rs b/tracing-appender/src/rolling/builder.rs index 3957556187..bae7e8cc92 100644 --- a/tracing-appender/src/rolling/builder.rs +++ b/tracing-appender/src/rolling/builder.rs @@ -63,7 +63,6 @@ impl RollingFileAppenderBuilder { log_filename_prefix, rotation: None, #[cfg(feature = "compression_gzip")] - #[cfg_attr(docsrs, doc(cfg(feature = "compression_gzip")))] compression: None, } } @@ -96,10 +95,10 @@ impl RollingFileAppenderBuilder { None } - /// Builds an instance of `RollingFileAppender` using previously defined attributes. + /// Returns a new [`RollingFileAppender`] with the configuration defined by this builder. pub fn build(self) -> RollingFileAppender { let now = OffsetDateTime::now_utc(); - let rotation = self.rotation.clone().unwrap_or(Rotation::NEVER).clone(); + let rotation = self.rotation.cloned().unwrap_or(Rotation::NEVER); let extension = self.get_extension(); let filename = rotation.join_date(self.log_filename_prefix.as_str(), &now, extension); let next_date = rotation.next_date(&now); From 4a1280cf41a17c20386133aec91ccc1f0c1d5e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Wed, 23 Feb 2022 14:27:36 +0100 Subject: [PATCH 20/22] Fix tests and apply PR suggestions --- .vscode/tasks.json | 4 ++++ tracing-appender/src/rolling/builder.rs | 19 +++++++++---------- tracing-appender/src/rolling/compression.rs | 9 ++++++--- tracing-appender/src/rolling/mod.rs | 4 ++-- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 1ca1d80290..e9867a3446 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -4,6 +4,10 @@ { "type": "cargo", "command": "build", + "args": [ + "--features", + "compression" + ], "problemMatcher": [ "$rustc" ], diff --git a/tracing-appender/src/rolling/builder.rs b/tracing-appender/src/rolling/builder.rs index bae7e8cc92..5551e1ca99 100644 --- a/tracing-appender/src/rolling/builder.rs +++ b/tracing-appender/src/rolling/builder.rs @@ -9,17 +9,16 @@ use std::sync::atomic::AtomicUsize; use time::OffsetDateTime; #[cfg(feature = "compression_gzip")] -use { - crate::rolling::compression::CompressionConfig, crate::rolling::compression::CompressionOption, -}; +use crate::rolling::compression::{CompressionConfig, CompressionOption}; use crate::writer::WriterChannel; -/// A builder for configuring new [`RollingFileAppender`]s. +/// A builder for configuring new [`RollingFileAppender`]s. /// -/// This can be used to configure additional options, such as adding compression. -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct RollingFileAppenderBuilder { +/// Note that `log_directory` and `log_filename_prefix` are obligatory parameters and should +/// be passed into the constructor of `RollingFileAppenderBuilder`. +#[derive(Debug, Clone)] +pub struct Builder { log_directory: String, log_filename_prefix: String, rotation: Option, @@ -27,7 +26,7 @@ pub struct RollingFileAppenderBuilder { compression: Option, } -impl RollingFileAppenderBuilder { +impl Builder { /// Creates a new `RollingFileAppnderBuilder` /// /// It was introduced to open up the possibility to use `compression` without @@ -58,7 +57,7 @@ impl RollingFileAppenderBuilder { .to_str() .expect("`log_directory` must not contain invalid UTF-8 characters") .to_string(); - RollingFileAppenderBuilder { + Builder { log_directory, log_filename_prefix, rotation: None, @@ -98,7 +97,7 @@ impl RollingFileAppenderBuilder { /// Returns a new [`RollingFileAppender`] with the configuration defined by this builder. pub fn build(self) -> RollingFileAppender { let now = OffsetDateTime::now_utc(); - let rotation = self.rotation.cloned().unwrap_or(Rotation::NEVER); + let rotation = self.rotation.clone().unwrap_or(Rotation::NEVER); let extension = self.get_extension(); let filename = rotation.join_date(self.log_filename_prefix.as_str(), &now, extension); let next_date = rotation.next_date(&now); diff --git a/tracing-appender/src/rolling/compression.rs b/tracing-appender/src/rolling/compression.rs index 9097e283f2..0ff288bc24 100644 --- a/tracing-appender/src/rolling/compression.rs +++ b/tracing-appender/src/rolling/compression.rs @@ -171,7 +171,7 @@ impl Into for CompressionOption { mod test { use crate::rolling::compression::CompressionOption; use crate::rolling::test::write_to_log; - use crate::rolling::{RollingFileAppenderBuilder, Rotation}; + use crate::rolling::{Builder, Rotation}; use flate2::read::GzDecoder; use std::fs; use std::io::Read; @@ -185,7 +185,9 @@ mod test { let bytes = fs::read(&path).expect("Cannot read bytes from compressed log"); let mut decoder = GzDecoder::new(&bytes[..]); let mut s = String::new(); - let _ = decoder.read_to_string(&mut s); + let r = decoder + .read_to_string(&mut s) + .expect("Cannot decode compressed log file"); if s.as_str() == expected_value { return true; } @@ -198,13 +200,14 @@ mod test { fn test_compressed_appender() { let file_prefix = "my-app-compressed-log"; let directory = tempfile::tempdir().expect("failed to create tempdir"); - let mut appender = RollingFileAppenderBuilder::new(directory.path(), file_prefix) + let mut appender = Builder::new(directory.path(), file_prefix) .rotation(Rotation::DAILY) .compression(CompressionOption::GzipFast) .build(); let expected_value = "Hello"; write_to_log(&mut appender, expected_value); + drop(appender); assert!(find_str_in_compressed_log(directory.path(), expected_value)); directory diff --git a/tracing-appender/src/rolling/mod.rs b/tracing-appender/src/rolling/mod.rs index d3ed747d58..57c362224a 100644 --- a/tracing-appender/src/rolling/mod.rs +++ b/tracing-appender/src/rolling/mod.rs @@ -27,7 +27,7 @@ //! # } //! ``` mod builder; -pub use crate::rolling::builder::RollingFileAppenderBuilder; +pub use crate::rolling::builder::Builder; #[cfg(feature = "compression_gzip")] use crate::rolling::compression::CompressionConfig; use crate::sync::{RwLock, RwLockReadGuard}; @@ -146,7 +146,7 @@ impl RollingFileAppender { directory: impl AsRef, file_name_prefix: impl AsRef, ) -> RollingFileAppender { - RollingFileAppenderBuilder::new(directory, file_name_prefix) + Builder::new(directory, file_name_prefix) .rotation(rotation) .build() } From 5504a9dae374e2c025a55f3662f32ad2f6975d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Wed, 23 Feb 2022 14:38:28 +0100 Subject: [PATCH 21/22] Final touches, format, clippy, docs --- tracing-appender/src/rolling/builder.rs | 56 ++++++++++++++------- tracing-appender/src/rolling/compression.rs | 2 +- tracing-appender/src/rolling/mod.rs | 6 +-- 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/tracing-appender/src/rolling/builder.rs b/tracing-appender/src/rolling/builder.rs index 5551e1ca99..198e494e81 100644 --- a/tracing-appender/src/rolling/builder.rs +++ b/tracing-appender/src/rolling/builder.rs @@ -27,25 +27,45 @@ pub struct Builder { } impl Builder { - /// Creates a new `RollingFileAppnderBuilder` + /// Returns a new builder for configuring a [`RollingFileAppender`], with + /// the provided log directory and filename prefix. /// - /// It was introduced to open up the possibility to use `compression` without - /// breaking the current interface. + /// Calling [`build`] on the returned builder will construct a new + /// [`RollingFileAppender`] that writes to files in the provided directory. + /// By default, log files will never be rotated and compression will not be + /// enabled. A rotation policy can be added to the builder using the + /// [`rotation`] method. When the "compression" feature flag is enabled, + /// compression can be configured using the [`compression`] method. /// - /// Note that `compression` module is enabled by using an optional feature flag - /// `compression_gzip` (for gzip algorithm) + /// # Panics /// - // # Examples - // ```rust - // # #[cfg(feature = "gzip_compression")] { - // use tracing_appender::builder::RollingFileAppenderBuilder; - // use tracing_appender::compression::CompressionOption; - // use tracing_appender::rolling::Rotation; - // let builder = RollingFileAppenderBuilder::new("/var/tmp", "my-app") - // .rotation(Rotation::DAILY) - // .compression(CompressionOption::GzipFast); - // # } - // ``` + /// This function panics if the provided log directory or log file prefix + /// are not valid UTF-8. + /// + /// # Examples + /// + /// Building a `RollingFileAppender` with the default configuration: + /// + /// ```rust + /// use tracing_appender::rolling::Builder; + /// let appender = Builder::new("/var/tmp", "my-app") + /// .build(); + /// ``` + /// + /// Enabling compression (needs a feature enabled `compression_gzip`): + /// + /// ```rust + /// #[cfg(feature = "compression_gzip")] + /// use tracing_appender::{ + /// rolling::{Builder, Rotation}, + /// rolling::compression::CompressionOption, + /// }; + /// #[cfg(feature = "compression_gzip")] + /// let appender = Builder::new("/var/tmp", "my-app") + /// .rotation(Rotation::DAILY) + /// .compression(CompressionOption::GzipFast) + /// .build(); + /// ``` pub fn new(log_directory: impl AsRef, log_filename_prefix: impl AsRef) -> Self { let log_directory = log_directory .as_ref() @@ -130,7 +150,7 @@ impl Builder { log_directory: self.log_directory, log_filename_prefix: self.log_filename_prefix, next_date, - rotation: rotation.clone(), + rotation, #[cfg(feature = "compression_gzip")] compression: self.compression, }, @@ -140,7 +160,7 @@ impl Builder { fn create_file_writer(&self, filename: &str) -> RwLock { let a = RwLock::new(WriterChannel::File( - create_writer_file(self.log_directory.as_str(), &filename) + create_writer_file(self.log_directory.as_str(), filename) .expect("failed to create appender"), )); a diff --git a/tracing-appender/src/rolling/compression.rs b/tracing-appender/src/rolling/compression.rs index 0ff288bc24..f85f219e70 100644 --- a/tracing-appender/src/rolling/compression.rs +++ b/tracing-appender/src/rolling/compression.rs @@ -185,7 +185,7 @@ mod test { let bytes = fs::read(&path).expect("Cannot read bytes from compressed log"); let mut decoder = GzDecoder::new(&bytes[..]); let mut s = String::new(); - let r = decoder + decoder .read_to_string(&mut s) .expect("Cannot decode compressed log file"); if s.as_str() == expected_value { diff --git a/tracing-appender/src/rolling/mod.rs b/tracing-appender/src/rolling/mod.rs index 57c362224a..e247afa438 100644 --- a/tracing-appender/src/rolling/mod.rs +++ b/tracing-appender/src/rolling/mod.rs @@ -90,10 +90,10 @@ pub mod compression; /// [`MakeWriter`]: tracing_subscriber::fmt::writer::MakeWriter #[derive(Debug)] pub struct RollingFileAppender { - pub(crate) state: Inner, - pub(crate) writer: RwLock, + state: Inner, + writer: RwLock, #[cfg(features = "compression")] - pub(crate) compression: Option, + compression: Option, } /// A [writer] that writes to a rolling log file. From 81bfc3267ce992e6334e35459135df98b74521dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Jankiewicz?= Date: Thu, 12 May 2022 09:42:14 +0200 Subject: [PATCH 22/22] Review fixes --- tracing-appender/src/rolling/builder.rs | 5 +- tracing-appender/src/rolling/compression.rs | 91 +++++++++++---------- 2 files changed, 49 insertions(+), 47 deletions(-) diff --git a/tracing-appender/src/rolling/builder.rs b/tracing-appender/src/rolling/builder.rs index 198e494e81..816a569893 100644 --- a/tracing-appender/src/rolling/builder.rs +++ b/tracing-appender/src/rolling/builder.rs @@ -159,10 +159,9 @@ impl Builder { } fn create_file_writer(&self, filename: &str) -> RwLock { - let a = RwLock::new(WriterChannel::File( + RwLock::new(WriterChannel::File( create_writer_file(self.log_directory.as_str(), filename) .expect("failed to create appender"), - )); - a + )) } } diff --git a/tracing-appender/src/rolling/compression.rs b/tracing-appender/src/rolling/compression.rs index f85f219e70..2ba4e09d4b 100644 --- a/tracing-appender/src/rolling/compression.rs +++ b/tracing-appender/src/rolling/compression.rs @@ -11,7 +11,7 @@ pub(crate) enum GzipCompressionLevelLiteral { } #[derive(Debug, Clone, Eq, PartialEq)] -#[repr(u32)] +#[repr(u8)] pub(crate) enum GzipCompressionLevelNumerical { Level0 = 0, Level1 = 1, @@ -59,10 +59,7 @@ pub(crate) enum CompressionConfig { impl CompressionConfig { pub(crate) fn gz_compress_level(&self) -> Compression { match self { - CompressionConfig::Gzip(gz) => { - let level = gz.level.clone().into(); - level - } + CompressionConfig::Gzip(gz) => gz.level.clone().into(), } } @@ -123,46 +120,52 @@ pub enum CompressionOption { impl Into for CompressionOption { fn into(self) -> CompressionConfig { + let new_gzip_literal = |level| -> CompressionConfig { + CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Literal(level), + }) + }; + + let new_gzip_numerical = |level| -> CompressionConfig { + CompressionConfig::Gzip(GzipCompression { + level: GzipCompressionLevel::Numerical(level), + }) + }; + match self { - CompressionOption::GzipNone => CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::None), - }), - CompressionOption::GzipFast => CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::Fast), - }), - CompressionOption::GzipBest => CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Literal(GzipCompressionLevelLiteral::Best), - }), - CompressionOption::GzipLevel0 => CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level0), - }), - CompressionOption::GzipLevel1 => CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level1), - }), - CompressionOption::GzipLevel2 => CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level2), - }), - CompressionOption::GzipLevel3 => CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level3), - }), - CompressionOption::GzipLevel4 => CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level4), - }), - CompressionOption::GzipLevel5 => CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level5), - }), - CompressionOption::GzipLevel6 => CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level6), - }), - CompressionOption::GzipLevel7 => CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level7), - }), - CompressionOption::GzipLevel8 => CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level8), - }), - CompressionOption::GzipLevel9 => CompressionConfig::Gzip(GzipCompression { - level: GzipCompressionLevel::Numerical(GzipCompressionLevelNumerical::Level9), - }), + CompressionOption::GzipNone => new_gzip_literal(GzipCompressionLevelLiteral::None), + CompressionOption::GzipFast => new_gzip_literal(GzipCompressionLevelLiteral::Fast), + CompressionOption::GzipBest => new_gzip_literal(GzipCompressionLevelLiteral::Best), + CompressionOption::GzipLevel0 => { + new_gzip_numerical(GzipCompressionLevelNumerical::Level0) + } + CompressionOption::GzipLevel1 => { + new_gzip_numerical(GzipCompressionLevelNumerical::Level1) + } + CompressionOption::GzipLevel2 => { + new_gzip_numerical(GzipCompressionLevelNumerical::Level2) + } + CompressionOption::GzipLevel3 => { + new_gzip_numerical(GzipCompressionLevelNumerical::Level3) + } + CompressionOption::GzipLevel4 => { + new_gzip_numerical(GzipCompressionLevelNumerical::Level4) + } + CompressionOption::GzipLevel5 => { + new_gzip_numerical(GzipCompressionLevelNumerical::Level5) + } + CompressionOption::GzipLevel6 => { + new_gzip_numerical(GzipCompressionLevelNumerical::Level6) + } + CompressionOption::GzipLevel7 => { + new_gzip_numerical(GzipCompressionLevelNumerical::Level7) + } + CompressionOption::GzipLevel8 => { + new_gzip_numerical(GzipCompressionLevelNumerical::Level8) + } + CompressionOption::GzipLevel9 => { + new_gzip_numerical(GzipCompressionLevelNumerical::Level9) + } } } }