Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show target instead of module path by default #209

Merged
merged 4 commits into from Jul 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/filter/mod.rs
Expand Up @@ -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 })
Expand All @@ -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),
}
}
Expand Down
125 changes: 115 additions & 10 deletions src/fmt/mod.rs
Expand Up @@ -141,6 +141,7 @@ pub(crate) type FormatFn = Box<dyn Fn(&mut Formatter, &Record) -> io::Result<()>
pub(crate) struct Builder {
pub format_timestamp: Option<TimestampPrecision>,
pub format_module_path: bool,
pub format_target: bool,
pub format_level: bool,
pub format_indent: Option<usize>,
pub custom_format: Option<FormatFn>,
Expand All @@ -152,7 +153,8 @@ impl Default for Builder {
fn default() -> Self {
Builder {
format_timestamp: Some(Default::default()),
format_module_path: true,
format_module_path: false,
format_target: true,
format_level: true,
format_indent: Some(4),
custom_format: None,
Expand Down Expand Up @@ -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,
Expand All @@ -210,6 +213,7 @@ type SubtleStyle = &'static str;
struct DefaultFormat<'a> {
timestamp: Option<TimestampPrecision>,
module_path: bool,
target: bool,
level: bool,
written_header_value: bool,
indent: Option<usize>,
Expand All @@ -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)
Expand Down Expand Up @@ -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("]");
Expand Down Expand Up @@ -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()
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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),
Expand All @@ -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),
Expand All @@ -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),
Expand All @@ -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,
Expand All @@ -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),
Expand All @@ -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);
}
}
42 changes: 29 additions & 13 deletions src/lib.rs
Expand Up @@ -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
Expand Down Expand Up @@ -598,6 +608,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<usize>) -> &mut Self {
Expand Down