From d2998a6ec685051b97f5b5c97427a61593bc6581 Mon Sep 17 00:00:00 2001 From: George Tsiamasiotis Date: Sat, 3 Jul 2021 22:37:48 +0300 Subject: [PATCH 1/4] Add option to print log target --- src/fmt/mod.rs | 123 +++++++++++++++++++++++++++++++++++++++++++++---- src/lib.rs | 6 +++ 2 files changed, 120 insertions(+), 9 deletions(-) diff --git a/src/fmt/mod.rs b/src/fmt/mod.rs index 3c4fee0a..271fdd6c 100644 --- a/src/fmt/mod.rs +++ b/src/fmt/mod.rs @@ -141,6 +141,7 @@ pub(crate) type FormatFn = Box io::Result<()> pub(crate) struct Builder { pub format_timestamp: Option, pub format_module_path: bool, + pub format_target: bool, pub format_level: bool, pub format_indent: Option, pub custom_format: Option, @@ -153,6 +154,7 @@ impl Default for Builder { Builder { format_timestamp: Some(Default::default()), format_module_path: true, + format_target: false, format_level: true, format_indent: Some(4), custom_format: None, @@ -186,6 +188,7 @@ impl Builder { let fmt = DefaultFormat { timestamp: built.format_timestamp, module_path: built.format_module_path, + target: built.format_target, level: built.format_level, written_header_value: false, indent: built.format_indent, @@ -210,6 +213,7 @@ type SubtleStyle = &'static str; struct DefaultFormat<'a> { timestamp: Option, module_path: bool, + target: bool, level: bool, written_header_value: bool, indent: Option, @@ -222,6 +226,7 @@ impl<'a> DefaultFormat<'a> { self.write_timestamp()?; self.write_level(record)?; self.write_module_path(record)?; + self.write_target(record)?; self.finish_header()?; self.write_args(record) @@ -311,6 +316,17 @@ impl<'a> DefaultFormat<'a> { } } + fn write_target(&mut self, record: &Record) -> io::Result<()> { + if !self.target { + return Ok(()); + } + + match record.target() { + "" => Ok(()), + target => self.write_header_value(target), + } + } + fn finish_header(&mut self) -> io::Result<()> { if self.written_header_value { let close_brace = self.subtle_style("]"); @@ -381,23 +397,33 @@ mod tests { use log::{Level, Record}; - fn write(fmt: DefaultFormat) -> String { + fn write_record(record: Record, fmt: DefaultFormat) -> String { let buf = fmt.buf.buf.clone(); - let record = Record::builder() - .args(format_args!("log\nmessage")) - .level(Level::Info) - .file(Some("test.rs")) - .line(Some(144)) - .module_path(Some("test::path")) - .build(); - fmt.write(&record).expect("failed to write record"); let buf = buf.borrow(); String::from_utf8(buf.bytes().to_vec()).expect("failed to read record") } + fn write_target<'a>(target: &'a str, fmt: DefaultFormat) -> String { + write_record( + Record::builder() + .args(format_args!("log\nmessage")) + .level(Level::Info) + .file(Some("test.rs")) + .line(Some(144)) + .module_path(Some("test::path")) + .target(target) + .build(), + fmt, + ) + } + + fn write(fmt: DefaultFormat) -> String { + write_target("", fmt) + } + #[test] fn format_with_header() { let writer = writer::Builder::new() @@ -409,6 +435,7 @@ mod tests { let written = write(DefaultFormat { timestamp: None, module_path: true, + target: false, level: true, written_header_value: false, indent: None, @@ -430,6 +457,7 @@ mod tests { let written = write(DefaultFormat { timestamp: None, module_path: false, + target: false, level: false, written_header_value: false, indent: None, @@ -451,6 +479,7 @@ mod tests { let written = write(DefaultFormat { timestamp: None, module_path: true, + target: false, level: true, written_header_value: false, indent: Some(4), @@ -472,6 +501,7 @@ mod tests { let written = write(DefaultFormat { timestamp: None, module_path: true, + target: false, level: true, written_header_value: false, indent: Some(0), @@ -493,6 +523,7 @@ mod tests { let written = write(DefaultFormat { timestamp: None, module_path: false, + target: false, level: false, written_header_value: false, indent: Some(4), @@ -514,6 +545,7 @@ mod tests { let written = write(DefaultFormat { timestamp: None, module_path: false, + target: false, level: false, written_header_value: false, indent: None, @@ -535,6 +567,7 @@ mod tests { let written = write(DefaultFormat { timestamp: None, module_path: false, + target: false, level: false, written_header_value: false, indent: Some(4), @@ -544,4 +577,76 @@ mod tests { assert_eq!("log\n\n message\n\n", written); } + + #[test] + fn format_target() { + let writer = writer::Builder::new() + .write_style(WriteStyle::Never) + .build(); + + let mut f = Formatter::new(&writer); + + let written = write_target( + "target", + DefaultFormat { + timestamp: None, + module_path: true, + target: true, + level: true, + written_header_value: false, + indent: None, + suffix: "\n", + buf: &mut f, + }, + ); + + assert_eq!("[INFO test::path target] log\nmessage\n", written); + } + + #[test] + fn format_empty_target() { + let writer = writer::Builder::new() + .write_style(WriteStyle::Never) + .build(); + + let mut f = Formatter::new(&writer); + + let written = write(DefaultFormat { + timestamp: None, + module_path: true, + target: true, + level: true, + written_header_value: false, + indent: None, + suffix: "\n", + buf: &mut f, + }); + + assert_eq!("[INFO test::path] log\nmessage\n", written); + } + + #[test] + fn format_no_target() { + let writer = writer::Builder::new() + .write_style(WriteStyle::Never) + .build(); + + let mut f = Formatter::new(&writer); + + let written = write_target( + "target", + DefaultFormat { + timestamp: None, + module_path: true, + target: false, + level: true, + written_header_value: false, + indent: None, + suffix: "\n", + buf: &mut f, + }, + ); + + assert_eq!("[INFO test::path] log\nmessage\n", written); + } } diff --git a/src/lib.rs b/src/lib.rs index 6a77266b..7e17289a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -598,6 +598,12 @@ impl Builder { self } + /// Whether or not to write the target in the default format. + pub fn format_target(&mut self, write: bool) -> &mut Self { + self.format.format_target = write; + self + } + /// Configures the amount of spaces to use to indent multiline log records. /// A value of `None` disables any kind of indentation. pub fn format_indent(&mut self, indent: Option) -> &mut Self { From 365ffafe45f615f65b88d67834aab16b132d9ecc Mon Sep 17 00:00:00 2001 From: George Tsiamasiotis Date: Sat, 3 Jul 2021 23:03:45 +0300 Subject: [PATCH 2/4] Show target instead of module path by default --- src/fmt/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fmt/mod.rs b/src/fmt/mod.rs index 271fdd6c..21e09577 100644 --- a/src/fmt/mod.rs +++ b/src/fmt/mod.rs @@ -153,8 +153,8 @@ impl Default for Builder { fn default() -> Self { Builder { format_timestamp: Some(Default::default()), - format_module_path: true, - format_target: false, + format_module_path: false, + format_target: true, format_level: true, format_indent: Some(4), custom_format: None, From 18884971d4eb1c268d61a4c37747de692bdd7124 Mon Sep 17 00:00:00 2001 From: George Tsiamasiotis Date: Sat, 3 Jul 2021 23:55:25 +0300 Subject: [PATCH 3/4] Clarified documentation about log filtering --- src/lib.rs | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7e17289a..e617efed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -97,28 +97,38 @@ //! directives*. A logging directive is of the form: //! //! ```text -//! path::to::module=level +//! example::log::target=level //! ``` //! -//! The path to the module is rooted in the name of the crate it was compiled -//! for, so if your program is contained in a file `hello.rs`, for example, to -//! turn on logging for this file you would use a value of `RUST_LOG=hello`. -//! Furthermore, this path is a prefix-search, so all modules nested in the -//! specified module will also have logging enabled. +//! The log target is typically equal to the path of the module the message +//! in question originated from, though it can be overriden. +//! +//! The path is rooted in the name of the crate it was compiled for, so if +//! your program is in a file called, for example, `hello.rs`, the path would +//! simply be be `hello`. +//! +//! Furthermore, the the log can be filtered using prefix-search based on the +//! specified log target. A value of, for example, `RUST_LOG=example`, would +//! match all of the messages with targets: +//! +//! * `example` +//! * `example::test` +//! * `example::test::module::submodule` +//! * `examples::and_more_examples` //! //! When providing the crate name or a module path, explicitly specifying the -//! log level is optional. If omitted, all logging for the item (and its -//! children) will be enabled. +//! log level is optional. If omitted, all logging for the item will be +//! enabled. //! //! The names of the log levels that may be specified correspond to the //! variations of the [`log::Level`][level-enum] enum from the `log` //! crate. They are: //! -//! * `error` -//! * `warn` -//! * `info` -//! * `debug` -//! * `trace` +//! * `error` +//! * `warn` +//! * `info` +//! * `debug` +//! * `trace` //! //! There is also a pseudo logging level, `off`, which may be specified to //! disable all logging for a given module or for the entire application. As From c5fa7a2c2d9ad3f5d2da0581ede4ab2e8944e104 Mon Sep 17 00:00:00 2001 From: mainrs <5113257+mainrs@users.noreply.github.com> Date: Wed, 14 Jul 2021 14:05:31 +0200 Subject: [PATCH 4/4] refactor: fix clippy warnings --- src/filter/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/filter/mod.rs b/src/filter/mod.rs index 7ef3f394..9ebeab0b 100644 --- a/src/filter/mod.rs +++ b/src/filter/mod.rs @@ -238,7 +238,7 @@ impl Builder { }); } else { // Consume map of directives. - let directives_map = mem::replace(&mut self.directives, HashMap::new()); + let directives_map = mem::take(&mut self.directives); directives = directives_map .into_iter() .map(|(name, level)| Directive { name, level }) @@ -253,7 +253,7 @@ impl Builder { } Filter { - directives: mem::replace(&mut directives, Vec::new()), + directives: mem::take(&mut directives), filter: mem::replace(&mut self.filter, None), } }