From 92e90a7999d7c2854582363dff538fcae5f2e2f3 Mon Sep 17 00:00:00 2001 From: Nicolas Avrutin Date: Sat, 15 Jul 2023 21:51:46 -0400 Subject: [PATCH] subscriber: add with_executable_name and with_process_id options. These options are useful when multiple processes are logging to the same destination (stderr, in the common case). This can happen when a process launches a child process or when a user simply launches multiple processes in the same terminal. Fixes #2447. Implement these two options. --- tracing-subscriber/src/fmt/fmt_subscriber.rs | 32 ++++++ tracing-subscriber/src/fmt/format/mod.rs | 109 +++++++++++++++++++ tracing-subscriber/src/fmt/mod.rs | 32 ++++++ 3 files changed, 173 insertions(+) diff --git a/tracing-subscriber/src/fmt/fmt_subscriber.rs b/tracing-subscriber/src/fmt/fmt_subscriber.rs index e3949b3361..9ad1621efa 100644 --- a/tracing-subscriber/src/fmt/fmt_subscriber.rs +++ b/tracing-subscriber/src/fmt/fmt_subscriber.rs @@ -523,6 +523,38 @@ where } } + /// Sets whether or not the binary name of the process is displayed when + /// formatting events. If executable_name is None, argv\[0\] will be used, + /// otherwise the spcified string will be used. + /// + /// [argv\[0\]]: std::env::args + pub fn with_executable_name( + self, + display_executable_name: bool, + executable_name: Option>, + ) -> Subscriber, W> { + Subscriber { + fmt_event: self + .fmt_event + .with_executable_name(display_executable_name, executable_name), + ..self + } + } + + /// Sets whether or not the [process ID] of the current thread is displayed + /// when formatting events. + /// + /// [process ID]: std::process::id + pub fn with_process_id( + self, + display_process_id: bool, + ) -> Subscriber, W> { + Subscriber { + fmt_event: self.fmt_event.with_process_id(display_process_id), + ..self + } + } + /// Sets whether or not the [thread ID] of the current thread is displayed /// when formatting events. /// diff --git a/tracing-subscriber/src/fmt/format/mod.rs b/tracing-subscriber/src/fmt/format/mod.rs index e19d689486..87fd2713c3 100644 --- a/tracing-subscriber/src/fmt/format/mod.rs +++ b/tracing-subscriber/src/fmt/format/mod.rs @@ -409,6 +409,9 @@ pub struct Format { pub(crate) display_timestamp: bool, pub(crate) display_target: bool, pub(crate) display_level: bool, + pub(crate) display_executable_name: bool, + pub(crate) executable_name: Option, + pub(crate) display_process_id: bool, pub(crate) display_thread_id: bool, pub(crate) display_thread_name: bool, pub(crate) display_filename: bool, @@ -599,6 +602,9 @@ impl Default for Format { display_timestamp: true, display_target: true, display_level: true, + display_executable_name: false, + executable_name: None, + display_process_id: false, display_thread_id: false, display_thread_name: false, display_filename: false, @@ -619,6 +625,9 @@ impl Format { display_target: false, display_timestamp: self.display_timestamp, display_level: self.display_level, + display_executable_name: self.display_executable_name, + executable_name: self.executable_name, + display_process_id: self.display_process_id, display_thread_id: self.display_thread_id, display_thread_name: self.display_thread_name, display_filename: self.display_filename, @@ -658,6 +667,9 @@ impl Format { display_target: self.display_target, display_timestamp: self.display_timestamp, display_level: self.display_level, + display_executable_name: self.display_executable_name, + executable_name: self.executable_name, + display_process_id: self.display_process_id, display_thread_id: self.display_thread_id, display_thread_name: self.display_thread_name, display_filename: true, @@ -690,6 +702,9 @@ impl Format { display_target: self.display_target, display_timestamp: self.display_timestamp, display_level: self.display_level, + display_executable_name: self.display_executable_name, + executable_name: self.executable_name, + display_process_id: self.display_process_id, display_thread_id: self.display_thread_id, display_thread_name: self.display_thread_name, display_filename: self.display_filename, @@ -719,6 +734,9 @@ impl Format { display_target: self.display_target, display_timestamp: self.display_timestamp, display_level: self.display_level, + display_executable_name: self.display_executable_name, + executable_name: self.executable_name, + display_process_id: self.display_process_id, display_thread_id: self.display_thread_id, display_thread_name: self.display_thread_name, display_filename: self.display_filename, @@ -735,6 +753,9 @@ impl Format { display_timestamp: false, display_target: self.display_target, display_level: self.display_level, + display_executable_name: self.display_executable_name, + executable_name: self.executable_name, + display_process_id: self.display_process_id, display_thread_id: self.display_thread_id, display_thread_name: self.display_thread_name, display_filename: self.display_filename, @@ -766,6 +787,34 @@ impl Format { } } + /// Sets whether or not the binary name of the process is displayed when + /// formatting events. If executable_name is None, argv\[0\] will be used, + /// otherwise the spcified string will be used. + /// + /// [argv\[0\]]: std::env::args + pub fn with_executable_name( + self, + display_executable_name: bool, + executable_name: Option>, + ) -> Format { + Format { + display_executable_name, + executable_name: executable_name.map(Into::into), + ..self + } + } + + /// Sets whether or not the [process ID] of the current thread is displayed + /// when formatting events. + /// + /// [process ID]: std::process::id + pub fn with_process_id(self, display_process_id: bool) -> Format { + Format { + display_process_id, + ..self + } + } + /// Sets whether or not the [thread ID] of the current thread is displayed /// when formatting events. /// @@ -951,6 +1000,20 @@ where self.format_timestamp(&mut writer)?; self.format_level(*meta.level(), &mut writer)?; + if self.display_executable_name { + if let Some(executable_name) = &self.executable_name { + write!(writer, "{} ", executable_name)?; + } else if let Some(argv0) = std::env::args().next() { + write!(writer, "{} ", argv0)?; + } else { + write!(writer, ") + .with_process_id(false) .with_thread_ids(false) .with_thread_names(false); #[cfg(feature = "ansi")] @@ -1793,6 +1858,50 @@ pub(super) mod test { assert_info_hello(subscriber, make_writer, expected); } + #[test] + fn with_automatic_executable_name() { + let make_writer = MockMakeWriter::default(); + let subscriber = crate::fmt::Collector::builder() + .with_writer(make_writer.clone()) + .with_executable_name(true, None::<&str>) + .with_ansi(false) + .with_timer(MockTime); + let expected = format!( + "fake time INFO {} tracing_subscriber::fmt::format::test: hello\n", + std::env::args().next().unwrap() + ); + + assert_info_hello(subscriber, make_writer, &expected); + } + + #[test] + fn with_manual_executable_name() { + let make_writer = MockMakeWriter::default(); + let subscriber = crate::fmt::Collector::builder() + .with_writer(make_writer.clone()) + .with_executable_name(true, Some("a_nice_rust_binary")) + .with_ansi(false) + .with_timer(MockTime); + let expected = + "fake time INFO a_nice_rust_binary tracing_subscriber::fmt::format::test: hello\n"; + + assert_info_hello(subscriber, make_writer, expected); + } + + #[test] + fn with_process_id() { + let make_writer = MockMakeWriter::default(); + let subscriber = crate::fmt::Collector::builder() + .with_writer(make_writer.clone()) + .with_process_id(true) + .with_ansi(false) + .with_timer(MockTime); + let expected = + "fake time INFO PID(NUMERIC) tracing_subscriber::fmt::format::test: hello\n"; + + assert_info_hello_ignore_numeric(subscriber, make_writer, expected); + } + #[test] fn with_thread_ids() { let make_writer = MockMakeWriter::default(); diff --git a/tracing-subscriber/src/fmt/mod.rs b/tracing-subscriber/src/fmt/mod.rs index 49e23e6007..123da58643 100644 --- a/tracing-subscriber/src/fmt/mod.rs +++ b/tracing-subscriber/src/fmt/mod.rs @@ -703,6 +703,38 @@ where } } + /// Sets whether or not the binary name of the process is displayed when + /// formatting events. If executable_name is None, argv\[0\] will be used, + /// otherwise the spcified string will be used. + /// + /// [argv\[0\]]: std::env::args + pub fn with_executable_name( + self, + display_executable_name: bool, + executable_name: Option>, + ) -> CollectorBuilder, F, W> { + CollectorBuilder { + inner: self + .inner + .with_executable_name(display_executable_name, executable_name), + ..self + } + } + + /// Sets whether or not the [process ID] of the current thread is displayed + /// when formatting events. + /// + /// [process ID]: std::process::id + pub fn with_process_id( + self, + display_process_id: bool, + ) -> CollectorBuilder, F, W> { + CollectorBuilder { + inner: self.inner.with_process_id(display_process_id), + ..self + } + } + /// Sets whether or not the [name] of the current thread is displayed /// when formatting events. ///