mirror of
https://github.com/tokio-rs/tracing.git
synced 2025-10-02 15:24:47 +00:00
subscriber: add Format::with_file
and with_line_number
(#1773)
## Motivation Logging line numbers and file names can be useful for debugging. This feature was suggested by #1326 ## Solution As per @hawkw's suggestions, fields were added on `Format`, along with builder methods. Filename and line number information was gathered from the `meta` variable. The `Pretty` formatter already supports printing source locations, but this is configured separately on the `Pretty` formatter rather than on the `Format` type. This branch also changes `Pretty` to honor the `Format`-level configurations and deprecates the `Pretty`-specific method. Fixes #1326 Closes #1804 Co-authored-by: David Barsky <me@davidbarsky.com> Co-authored-by: Eliza Weisman <eliza@buoyant.io>
This commit is contained in:
parent
1e0bfc4d19
commit
35d177626b
@ -26,6 +26,8 @@ This directory contains a collection of examples that demonstrate the use of the
|
|||||||
events.
|
events.
|
||||||
+ `fmt-multiple-writers.rs`: demonstrates how `fmt::Layer` can write
|
+ `fmt-multiple-writers.rs`: demonstrates how `fmt::Layer` can write
|
||||||
to multiple destinations (in this instance, stdout and a file) simultaneously.
|
to multiple destinations (in this instance, stdout and a file) simultaneously.
|
||||||
|
+ `fmt-source-locations.rs`: demonstrates displaying source code locations
|
||||||
|
with `fmt::Layer`.
|
||||||
+ `subscriber-filter`: Demonstrates the `tracing-subscriber::filter` module,
|
+ `subscriber-filter`: Demonstrates the `tracing-subscriber::filter` module,
|
||||||
which provides a layer which adds configurable filtering to a subscriber
|
which provides a layer which adds configurable filtering to a subscriber
|
||||||
implementation.
|
implementation.
|
||||||
|
29
examples/examples/fmt-source-locations.rs
Normal file
29
examples/examples/fmt-source-locations.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
//! Demonstrates displaying events' source code locations with the `fmt`
|
||||||
|
//! subscriber.
|
||||||
|
#![deny(rust_2018_idioms)]
|
||||||
|
#[path = "fmt/yak_shave.rs"]
|
||||||
|
mod yak_shave;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
tracing_subscriber::fmt()
|
||||||
|
// enable everything
|
||||||
|
.with_max_level(tracing::Level::TRACE)
|
||||||
|
// display source code file paths
|
||||||
|
.with_file(true)
|
||||||
|
// display source code line numbers
|
||||||
|
.with_line_number(true)
|
||||||
|
// disable targets
|
||||||
|
.with_target(false)
|
||||||
|
// sets this to be the default, global collector for this application.
|
||||||
|
.init();
|
||||||
|
|
||||||
|
let number_of_yaks = 3;
|
||||||
|
// this creates a new event, outside of any spans.
|
||||||
|
tracing::info!(number_of_yaks, "preparing to shave yaks");
|
||||||
|
|
||||||
|
let number_shaved = yak_shave::shave_all(number_of_yaks);
|
||||||
|
tracing::info!(
|
||||||
|
all_yaks_shaved = number_shaved == number_of_yaks,
|
||||||
|
"yak shaving completed."
|
||||||
|
);
|
||||||
|
}
|
@ -299,6 +299,30 @@ where
|
|||||||
..self
|
..self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Sets whether or not an event's [source code file path][file] is
|
||||||
|
/// displayed.
|
||||||
|
///
|
||||||
|
/// [file]: tracing_core::Metadata::file
|
||||||
|
pub fn with_file(self, display_filename: bool) -> Layer<S, N, format::Format<L, T>, W> {
|
||||||
|
Layer {
|
||||||
|
fmt_event: self.fmt_event.with_file(display_filename),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets whether or not an event's [source code line number][line] is
|
||||||
|
/// displayed.
|
||||||
|
///
|
||||||
|
/// [line]: tracing_core::Metadata::line
|
||||||
|
pub fn with_line_number(
|
||||||
|
self,
|
||||||
|
display_line_number: bool,
|
||||||
|
) -> Layer<S, N, format::Format<L, T>, W> {
|
||||||
|
Layer {
|
||||||
|
fmt_event: self.fmt_event.with_line_number(display_line_number),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets whether or not an event's level is displayed.
|
/// Sets whether or not an event's level is displayed.
|
||||||
pub fn with_level(self, display_level: bool) -> Layer<S, N, format::Format<L, T>, W> {
|
pub fn with_level(self, display_level: bool) -> Layer<S, N, format::Format<L, T>, W> {
|
||||||
|
@ -243,6 +243,18 @@ where
|
|||||||
serializer.serialize_entry("target", meta.target())?;
|
serializer.serialize_entry("target", meta.target())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.display_filename {
|
||||||
|
if let Some(filename) = meta.file() {
|
||||||
|
serializer.serialize_entry("filename", filename)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.display_line_number {
|
||||||
|
if let Some(line_number) = meta.line() {
|
||||||
|
serializer.serialize_entry("line_number", &line_number)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if self.format.display_current_span {
|
if self.format.display_current_span {
|
||||||
if let Some(ref span) = current_span {
|
if let Some(ref span) = current_span {
|
||||||
serializer
|
serializer
|
||||||
@ -488,6 +500,7 @@ mod test {
|
|||||||
use tracing::{self, subscriber::with_default};
|
use tracing::{self, subscriber::with_default};
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
struct MockTime;
|
struct MockTime;
|
||||||
impl FormatTime for MockTime {
|
impl FormatTime for MockTime {
|
||||||
@ -515,6 +528,50 @@ mod test {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn json_filename() {
|
||||||
|
let current_path = Path::new("tracing-subscriber")
|
||||||
|
.join("src")
|
||||||
|
.join("fmt")
|
||||||
|
.join("format")
|
||||||
|
.join("json.rs")
|
||||||
|
.to_str()
|
||||||
|
.expect("path must be valid unicode")
|
||||||
|
// escape windows backslashes
|
||||||
|
.replace('\\', "\\\\");
|
||||||
|
let expected =
|
||||||
|
&format!("{}{}{}",
|
||||||
|
"{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"answer\":42,\"name\":\"json_span\",\"number\":3},\"spans\":[{\"answer\":42,\"name\":\"json_span\",\"number\":3}],\"target\":\"tracing_subscriber::fmt::format::json::test\",\"filename\":\"",
|
||||||
|
current_path,
|
||||||
|
"\",\"fields\":{\"message\":\"some json test\"}}\n");
|
||||||
|
let subscriber = subscriber()
|
||||||
|
.flatten_event(false)
|
||||||
|
.with_current_span(true)
|
||||||
|
.with_file(true)
|
||||||
|
.with_span_list(true);
|
||||||
|
test_json(expected, subscriber, || {
|
||||||
|
let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3);
|
||||||
|
let _guard = span.enter();
|
||||||
|
tracing::info!("some json test");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn json_line_number() {
|
||||||
|
let expected =
|
||||||
|
"{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"answer\":42,\"name\":\"json_span\",\"number\":3},\"spans\":[{\"answer\":42,\"name\":\"json_span\",\"number\":3}],\"target\":\"tracing_subscriber::fmt::format::json::test\",\"line_number\":42,\"fields\":{\"message\":\"some json test\"}}\n";
|
||||||
|
let subscriber = subscriber()
|
||||||
|
.flatten_event(false)
|
||||||
|
.with_current_span(true)
|
||||||
|
.with_line_number(true)
|
||||||
|
.with_span_list(true);
|
||||||
|
test_json_with_line_number(expected, subscriber, || {
|
||||||
|
let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3);
|
||||||
|
let _guard = span.enter();
|
||||||
|
tracing::info!("some json test");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn json_flattened_event() {
|
fn json_flattened_event() {
|
||||||
let expected =
|
let expected =
|
||||||
@ -747,4 +804,34 @@ mod test {
|
|||||||
serde_json::from_str(actual).unwrap()
|
serde_json::from_str(actual).unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_json_with_line_number<T>(
|
||||||
|
expected: &str,
|
||||||
|
builder: crate::fmt::SubscriberBuilder<JsonFields, Format<Json>>,
|
||||||
|
producer: impl FnOnce() -> T,
|
||||||
|
) {
|
||||||
|
let make_writer = MockMakeWriter::default();
|
||||||
|
let subscriber = builder
|
||||||
|
.with_writer(make_writer.clone())
|
||||||
|
.with_timer(MockTime)
|
||||||
|
.finish();
|
||||||
|
|
||||||
|
with_default(subscriber, producer);
|
||||||
|
|
||||||
|
let buf = make_writer.buf();
|
||||||
|
let actual = std::str::from_utf8(&buf[..]).unwrap();
|
||||||
|
let mut expected =
|
||||||
|
serde_json::from_str::<std::collections::HashMap<&str, serde_json::Value>>(expected)
|
||||||
|
.unwrap();
|
||||||
|
let expect_line_number = expected.remove("line_number").is_some();
|
||||||
|
let mut actual: std::collections::HashMap<&str, serde_json::Value> =
|
||||||
|
serde_json::from_str(actual).unwrap();
|
||||||
|
let line_number = actual.remove("line_number");
|
||||||
|
if expect_line_number {
|
||||||
|
assert_eq!(line_number.map(|x| x.is_number()), Some(true));
|
||||||
|
} else {
|
||||||
|
assert!(line_number.is_none());
|
||||||
|
}
|
||||||
|
assert_eq!(actual, expected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,6 +325,8 @@ pub struct Format<F = Full, T = SystemTime> {
|
|||||||
pub(crate) display_level: bool,
|
pub(crate) display_level: bool,
|
||||||
pub(crate) display_thread_id: bool,
|
pub(crate) display_thread_id: bool,
|
||||||
pub(crate) display_thread_name: bool,
|
pub(crate) display_thread_name: bool,
|
||||||
|
pub(crate) display_filename: bool,
|
||||||
|
pub(crate) display_line_number: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// === impl Writer ===
|
// === impl Writer ===
|
||||||
@ -501,6 +503,8 @@ impl Default for Format<Full, SystemTime> {
|
|||||||
display_level: true,
|
display_level: true,
|
||||||
display_thread_id: false,
|
display_thread_id: false,
|
||||||
display_thread_name: false,
|
display_thread_name: false,
|
||||||
|
display_filename: false,
|
||||||
|
display_line_number: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -519,6 +523,8 @@ impl<F, T> Format<F, T> {
|
|||||||
display_level: self.display_level,
|
display_level: self.display_level,
|
||||||
display_thread_id: self.display_thread_id,
|
display_thread_id: self.display_thread_id,
|
||||||
display_thread_name: self.display_thread_name,
|
display_thread_name: self.display_thread_name,
|
||||||
|
display_filename: self.display_filename,
|
||||||
|
display_line_number: self.display_line_number,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,6 +562,8 @@ impl<F, T> Format<F, T> {
|
|||||||
display_level: self.display_level,
|
display_level: self.display_level,
|
||||||
display_thread_id: self.display_thread_id,
|
display_thread_id: self.display_thread_id,
|
||||||
display_thread_name: self.display_thread_name,
|
display_thread_name: self.display_thread_name,
|
||||||
|
display_filename: true,
|
||||||
|
display_line_number: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,6 +595,8 @@ impl<F, T> Format<F, T> {
|
|||||||
display_level: self.display_level,
|
display_level: self.display_level,
|
||||||
display_thread_id: self.display_thread_id,
|
display_thread_id: self.display_thread_id,
|
||||||
display_thread_name: self.display_thread_name,
|
display_thread_name: self.display_thread_name,
|
||||||
|
display_filename: self.display_filename,
|
||||||
|
display_line_number: self.display_line_number,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -614,6 +624,8 @@ impl<F, T> Format<F, T> {
|
|||||||
display_level: self.display_level,
|
display_level: self.display_level,
|
||||||
display_thread_id: self.display_thread_id,
|
display_thread_id: self.display_thread_id,
|
||||||
display_thread_name: self.display_thread_name,
|
display_thread_name: self.display_thread_name,
|
||||||
|
display_filename: self.display_filename,
|
||||||
|
display_line_number: self.display_line_number,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,6 +640,8 @@ impl<F, T> Format<F, T> {
|
|||||||
display_level: self.display_level,
|
display_level: self.display_level,
|
||||||
display_thread_id: self.display_thread_id,
|
display_thread_id: self.display_thread_id,
|
||||||
display_thread_name: self.display_thread_name,
|
display_thread_name: self.display_thread_name,
|
||||||
|
display_filename: self.display_filename,
|
||||||
|
display_line_number: self.display_line_number,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -677,6 +691,38 @@ impl<F, T> Format<F, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets whether or not an event's [source code file path][file] is
|
||||||
|
/// displayed.
|
||||||
|
///
|
||||||
|
/// [file]: tracing_core::Metadata::file
|
||||||
|
pub fn with_file(self, display_filename: bool) -> Format<F, T> {
|
||||||
|
Format {
|
||||||
|
display_filename,
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets whether or not an event's [source code line number][line] is
|
||||||
|
/// displayed.
|
||||||
|
///
|
||||||
|
/// [line]: tracing_core::Metadata::line
|
||||||
|
pub fn with_line_number(self, display_line_number: bool) -> Format<F, T> {
|
||||||
|
Format {
|
||||||
|
display_line_number,
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets whether or not the source code location from which an event
|
||||||
|
/// originated is displayed.
|
||||||
|
///
|
||||||
|
/// This is equivalent to calling [`Format::with_file`] and
|
||||||
|
/// [`Format::with_line_number`] with the same value.
|
||||||
|
pub fn with_source_location(self, display_location: bool) -> Self {
|
||||||
|
self.with_line_number(display_location)
|
||||||
|
.with_file(display_location)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn format_timestamp(&self, writer: &mut Writer<'_>) -> fmt::Result
|
fn format_timestamp(&self, writer: &mut Writer<'_>) -> fmt::Result
|
||||||
where
|
where
|
||||||
@ -852,6 +898,34 @@ where
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let line_number = if self.display_line_number {
|
||||||
|
meta.line()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.display_filename {
|
||||||
|
if let Some(filename) = meta.file() {
|
||||||
|
write!(
|
||||||
|
writer,
|
||||||
|
"{}{}{}",
|
||||||
|
dimmed.paint(filename),
|
||||||
|
dimmed.paint(":"),
|
||||||
|
if line_number.is_some() { "" } else { " " }
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(line_number) = line_number {
|
||||||
|
write!(
|
||||||
|
writer,
|
||||||
|
"{}{}:{} ",
|
||||||
|
dimmed.prefix(),
|
||||||
|
line_number,
|
||||||
|
dimmed.suffix()
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
ctx.format_fields(writer.by_ref(), event)?;
|
ctx.format_fields(writer.by_ref(), event)?;
|
||||||
writeln!(writer)
|
writeln!(writer)
|
||||||
}
|
}
|
||||||
@ -930,18 +1004,45 @@ where
|
|||||||
};
|
};
|
||||||
write!(writer, "{}", fmt_ctx)?;
|
write!(writer, "{}", fmt_ctx)?;
|
||||||
|
|
||||||
|
let bold = writer.bold();
|
||||||
|
let dimmed = writer.dimmed();
|
||||||
|
|
||||||
|
let mut needs_space = false;
|
||||||
if self.display_target {
|
if self.display_target {
|
||||||
|
write!(writer, "{}{}", bold.paint(meta.target()), dimmed.paint(":"))?;
|
||||||
|
needs_space = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.display_filename {
|
||||||
|
if let Some(filename) = meta.file() {
|
||||||
|
if self.display_target {
|
||||||
|
writer.write_char(' ')?;
|
||||||
|
}
|
||||||
|
write!(writer, "{}{}", bold.paint(filename), dimmed.paint(":"))?;
|
||||||
|
needs_space = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.display_line_number {
|
||||||
|
if let Some(line_number) = meta.line() {
|
||||||
write!(
|
write!(
|
||||||
writer,
|
writer,
|
||||||
"{}{} ",
|
"{}{}{}{}",
|
||||||
writer.bold().paint(meta.target()),
|
bold.prefix(),
|
||||||
writer.dimmed().paint(":")
|
line_number,
|
||||||
|
bold.suffix(),
|
||||||
|
dimmed.paint(":")
|
||||||
)?;
|
)?;
|
||||||
|
needs_space = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if needs_space {
|
||||||
|
writer.write_char(' ')?;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.format_fields(writer.by_ref(), event)?;
|
ctx.format_fields(writer.by_ref(), event)?;
|
||||||
|
|
||||||
let dimmed = writer.dimmed();
|
|
||||||
for span in ctx
|
for span in ctx
|
||||||
.event_scope()
|
.event_scope()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -1213,6 +1314,14 @@ impl Style {
|
|||||||
fn paint(&self, d: impl fmt::Display) -> impl fmt::Display {
|
fn paint(&self, d: impl fmt::Display) -> impl fmt::Display {
|
||||||
d
|
d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prefix(&self) -> impl fmt::Display {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
|
fn suffix(&self) -> impl fmt::Display {
|
||||||
|
""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FmtThreadName<'a> {
|
struct FmtThreadName<'a> {
|
||||||
@ -1540,9 +1649,9 @@ pub(super) mod test {
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
use std::{fmt, path::Path};
|
||||||
|
|
||||||
pub(crate) struct MockTime;
|
pub(crate) struct MockTime;
|
||||||
impl FormatTime for MockTime {
|
impl FormatTime for MockTime {
|
||||||
@ -1612,6 +1721,99 @@ pub(super) mod test {
|
|||||||
run_test(subscriber, make_writer, expected);
|
run_test(subscriber, make_writer, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn with_line_number_and_file_name() {
|
||||||
|
let make_writer = MockMakeWriter::default();
|
||||||
|
let subscriber = crate::fmt::Subscriber::builder()
|
||||||
|
.with_writer(make_writer.clone())
|
||||||
|
.with_file(true)
|
||||||
|
.with_line_number(true)
|
||||||
|
.with_level(false)
|
||||||
|
.with_ansi(false)
|
||||||
|
.with_timer(MockTime);
|
||||||
|
|
||||||
|
let expected = Regex::new(&format!(
|
||||||
|
"^fake time tracing_subscriber::fmt::format::test: {}:[0-9]+: hello\n$",
|
||||||
|
current_path()
|
||||||
|
// if we're on Windows, the path might contain backslashes, which
|
||||||
|
// have to be escpaed before compiling the regex.
|
||||||
|
.replace('\\', "\\\\")
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
let _default = set_default(&subscriber.into());
|
||||||
|
tracing::info!("hello");
|
||||||
|
let res = make_writer.get_string();
|
||||||
|
assert!(expected.is_match(&res));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn with_line_number() {
|
||||||
|
let make_writer = MockMakeWriter::default();
|
||||||
|
let subscriber = crate::fmt::Subscriber::builder()
|
||||||
|
.with_writer(make_writer.clone())
|
||||||
|
.with_line_number(true)
|
||||||
|
.with_level(false)
|
||||||
|
.with_ansi(false)
|
||||||
|
.with_timer(MockTime);
|
||||||
|
|
||||||
|
let expected =
|
||||||
|
Regex::new("^fake time tracing_subscriber::fmt::format::test: [0-9]+: hello\n$")
|
||||||
|
.unwrap();
|
||||||
|
let _default = set_default(&subscriber.into());
|
||||||
|
tracing::info!("hello");
|
||||||
|
let res = make_writer.get_string();
|
||||||
|
assert!(expected.is_match(&res));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn with_filename() {
|
||||||
|
let make_writer = MockMakeWriter::default();
|
||||||
|
let subscriber = crate::fmt::Subscriber::builder()
|
||||||
|
.with_writer(make_writer.clone())
|
||||||
|
.with_file(true)
|
||||||
|
.with_level(false)
|
||||||
|
.with_ansi(false)
|
||||||
|
.with_timer(MockTime);
|
||||||
|
let expected = &format!(
|
||||||
|
"fake time tracing_subscriber::fmt::format::test: {}: hello\n",
|
||||||
|
current_path(),
|
||||||
|
);
|
||||||
|
assert_info_hello(subscriber, make_writer, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn with_thread_ids() {
|
||||||
|
let make_writer = MockMakeWriter::default();
|
||||||
|
let subscriber = crate::fmt::Subscriber::builder()
|
||||||
|
.with_writer(make_writer.clone())
|
||||||
|
.with_thread_ids(true)
|
||||||
|
.with_ansi(false)
|
||||||
|
.with_timer(MockTime);
|
||||||
|
let expected =
|
||||||
|
"fake time INFO ThreadId(NUMERIC) tracing_subscriber::fmt::format::test: hello\n";
|
||||||
|
|
||||||
|
assert_info_hello_ignore_numeric(subscriber, make_writer, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pretty_default() {
|
||||||
|
let make_writer = MockMakeWriter::default();
|
||||||
|
let subscriber = crate::fmt::Subscriber::builder()
|
||||||
|
.pretty()
|
||||||
|
.with_writer(make_writer.clone())
|
||||||
|
.with_ansi(false)
|
||||||
|
.with_timer(MockTime);
|
||||||
|
let expected = format!(
|
||||||
|
r#" fake time INFO tracing_subscriber::fmt::format::test: hello
|
||||||
|
at {}:NUMERIC
|
||||||
|
|
||||||
|
"#,
|
||||||
|
file!()
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_info_hello_ignore_numeric(subscriber, make_writer, &expected)
|
||||||
|
}
|
||||||
|
|
||||||
fn assert_info_hello(subscriber: impl Into<Dispatch>, buf: MockMakeWriter, expected: &str) {
|
fn assert_info_hello(subscriber: impl Into<Dispatch>, buf: MockMakeWriter, expected: &str) {
|
||||||
let _default = set_default(&subscriber.into());
|
let _default = set_default(&subscriber.into());
|
||||||
tracing::info!("hello");
|
tracing::info!("hello");
|
||||||
@ -1645,14 +1847,14 @@ pub(super) mod test {
|
|||||||
T: Send + Sync + 'static,
|
T: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
let make_writer = MockMakeWriter::default();
|
let make_writer = MockMakeWriter::default();
|
||||||
let collector = builder
|
let subscriber = builder
|
||||||
.with_writer(make_writer.clone())
|
.with_writer(make_writer.clone())
|
||||||
.with_level(false)
|
.with_level(false)
|
||||||
.with_ansi(false)
|
.with_ansi(false)
|
||||||
.with_timer(MockTime)
|
.with_timer(MockTime)
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
with_default(collector, || {
|
with_default(subscriber, || {
|
||||||
let span1 = tracing::info_span!("span1", span = 1);
|
let span1 = tracing::info_span!("span1", span = 1);
|
||||||
let span2 = tracing::info_span!(parent: &span1, "span2", span = 2);
|
let span2 = tracing::info_span!(parent: &span1, "span2", span = 2);
|
||||||
tracing::info!(parent: &span2, "hello");
|
tracing::info!(parent: &span2, "hello");
|
||||||
@ -1869,4 +2071,16 @@ pub(super) mod test {
|
|||||||
assert!(!f.contains(FmtSpan::EXIT));
|
assert!(!f.contains(FmtSpan::EXIT));
|
||||||
assert!(f.contains(FmtSpan::CLOSE));
|
assert!(f.contains(FmtSpan::CLOSE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the test's module path.
|
||||||
|
fn current_path() -> String {
|
||||||
|
Path::new("tracing-subscriber")
|
||||||
|
.join("src")
|
||||||
|
.join("fmt")
|
||||||
|
.join("format")
|
||||||
|
.join("mod.rs")
|
||||||
|
.to_str()
|
||||||
|
.expect("path must not contain invalid unicode")
|
||||||
|
.to_owned()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,10 @@ impl Pretty {
|
|||||||
/// Sets whether the event's source code location is displayed.
|
/// Sets whether the event's source code location is displayed.
|
||||||
///
|
///
|
||||||
/// This defaults to `true`.
|
/// This defaults to `true`.
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.3.6",
|
||||||
|
note = "all formatters now support configurable source locations. Use `Format::with_source_location` instead."
|
||||||
|
)]
|
||||||
pub fn with_source_location(self, display_location: bool) -> Self {
|
pub fn with_source_location(self, display_location: bool) -> Self {
|
||||||
Self {
|
Self {
|
||||||
display_location,
|
display_location,
|
||||||
@ -84,17 +88,6 @@ impl Pretty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Format<Pretty, T> {
|
|
||||||
/// Sets whether or not the source code location from which an event
|
|
||||||
/// originated is displayed.
|
|
||||||
///
|
|
||||||
/// This defaults to `true`.
|
|
||||||
pub fn with_source_location(mut self, display_location: bool) -> Self {
|
|
||||||
self.format = self.format.with_source_location(display_location);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C, N, T> FormatEvent<C, N> for Format<Pretty, T>
|
impl<C, N, T> FormatEvent<C, N> for Format<Pretty, T>
|
||||||
where
|
where
|
||||||
C: Subscriber + for<'a> LookupSpan<'a>,
|
C: Subscriber + for<'a> LookupSpan<'a>,
|
||||||
@ -147,12 +140,37 @@ where
|
|||||||
};
|
};
|
||||||
write!(
|
write!(
|
||||||
writer,
|
writer,
|
||||||
"{}{}{}: ",
|
"{}{}{}:",
|
||||||
target_style.prefix(),
|
target_style.prefix(),
|
||||||
meta.target(),
|
meta.target(),
|
||||||
target_style.infix(style)
|
target_style.infix(style)
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
let line_number = if self.display_line_number {
|
||||||
|
meta.line()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// If the file name is disabled, format the line number right after the
|
||||||
|
// target. Otherwise, if we also display the file, it'll go on a
|
||||||
|
// separate line.
|
||||||
|
if let (Some(line_number), false, true) = (
|
||||||
|
line_number,
|
||||||
|
self.display_filename,
|
||||||
|
self.format.display_location,
|
||||||
|
) {
|
||||||
|
write!(
|
||||||
|
writer,
|
||||||
|
"{}{}{}:",
|
||||||
|
style.prefix(),
|
||||||
|
line_number,
|
||||||
|
style.infix(style)
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.write_char(' ')?;
|
||||||
|
|
||||||
let mut v = PrettyVisitor::new(writer.by_ref(), true).with_style(style);
|
let mut v = PrettyVisitor::new(writer.by_ref(), true).with_style(style);
|
||||||
event.record(&mut v);
|
event.record(&mut v);
|
||||||
v.finish()?;
|
v.finish()?;
|
||||||
@ -164,20 +182,21 @@ where
|
|||||||
Style::new()
|
Style::new()
|
||||||
};
|
};
|
||||||
let thread = self.display_thread_name || self.display_thread_id;
|
let thread = self.display_thread_name || self.display_thread_id;
|
||||||
if let (true, Some(file), Some(line)) =
|
|
||||||
(self.format.display_location, meta.file(), meta.line())
|
if let (Some(file), true, true) = (
|
||||||
{
|
meta.file(),
|
||||||
write!(
|
self.format.display_location,
|
||||||
writer,
|
self.display_filename,
|
||||||
" {} {}:{}{}",
|
) {
|
||||||
dimmed.paint("at"),
|
write!(writer, " {} {}", dimmed.paint("at"), file,)?;
|
||||||
file,
|
|
||||||
line,
|
if let Some(line) = line_number {
|
||||||
dimmed.paint(if thread { " " } else { "\n" })
|
write!(writer, ":{}", line)?;
|
||||||
)?;
|
}
|
||||||
|
writer.write_char(if thread { ' ' } else { '\n' })?;
|
||||||
} else if thread {
|
} else if thread {
|
||||||
write!(writer, " ")?;
|
write!(writer, " ")?;
|
||||||
}
|
};
|
||||||
|
|
||||||
if thread {
|
if thread {
|
||||||
write!(writer, "{} ", dimmed.paint("on"))?;
|
write!(writer, "{} ", dimmed.paint("on"))?;
|
||||||
|
@ -734,6 +734,34 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets whether or not an event's [source code file path][file] is
|
||||||
|
/// displayed.
|
||||||
|
///
|
||||||
|
/// [file]: tracing_core::Metadata::file
|
||||||
|
pub fn with_file(
|
||||||
|
self,
|
||||||
|
display_filename: bool,
|
||||||
|
) -> SubscriberBuilder<N, format::Format<L, T>, F, W> {
|
||||||
|
SubscriberBuilder {
|
||||||
|
inner: self.inner.with_file(display_filename),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets whether or not an event's [source code line number][line] is
|
||||||
|
/// displayed.
|
||||||
|
///
|
||||||
|
/// [line]: tracing_core::Metadata::line
|
||||||
|
pub fn with_line_number(
|
||||||
|
self,
|
||||||
|
display_line_number: bool,
|
||||||
|
) -> SubscriberBuilder<N, format::Format<L, T>, F, W> {
|
||||||
|
SubscriberBuilder {
|
||||||
|
inner: self.inner.with_line_number(display_line_number),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets whether or not an event's level is displayed.
|
/// Sets whether or not an event's level is displayed.
|
||||||
pub fn with_level(
|
pub fn with_level(
|
||||||
self,
|
self,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user