Skip to content

Commit a338a1a

Browse files
committed
subscriber: add with_binary_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.
1 parent 27f688e commit a338a1a

File tree

3 files changed

+179
-1
lines changed

3 files changed

+179
-1
lines changed

tracing-subscriber/src/fmt/fmt_subscriber.rs

+32
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,38 @@ where
490490
}
491491
}
492492

493+
/// Sets whether or not the binary name of the process is displayed when
494+
/// formatting events. If executable_name is None, argv\[0\] will be used,
495+
/// otherwise the spcified string will be used.
496+
///
497+
/// [argv\[0\]]: std::env::args
498+
pub fn with_executable_name(
499+
self,
500+
display_executable_name: bool,
501+
executable_name: Option<impl Into<String>>,
502+
) -> Subscriber<C, N, format::Format<L, T>, W> {
503+
Subscriber {
504+
fmt_event: self
505+
.fmt_event
506+
.with_executable_name(display_executable_name, executable_name),
507+
..self
508+
}
509+
}
510+
511+
/// Sets whether or not the [process ID] of the current thread is displayed
512+
/// when formatting events.
513+
///
514+
/// [process ID]: std::process::id
515+
pub fn with_process_id(
516+
self,
517+
display_process_id: bool,
518+
) -> Subscriber<C, N, format::Format<L, T>, W> {
519+
Subscriber {
520+
fmt_event: self.fmt_event.with_process_id(display_process_id),
521+
..self
522+
}
523+
}
524+
493525
/// Sets whether or not the [thread ID] of the current thread is displayed
494526
/// when formatting events.
495527
///

tracing-subscriber/src/fmt/format/mod.rs

+115-1
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,9 @@ pub struct Format<F = Full, T = SystemTime> {
410410
pub(crate) display_timestamp: bool,
411411
pub(crate) display_target: bool,
412412
pub(crate) display_level: bool,
413+
pub(crate) display_executable_name: bool,
414+
pub(crate) executable_name: Option<String>,
415+
pub(crate) display_process_id: bool,
413416
pub(crate) display_thread_id: bool,
414417
pub(crate) display_thread_name: bool,
415418
pub(crate) display_filename: bool,
@@ -588,6 +591,9 @@ impl Default for Format<Full, SystemTime> {
588591
display_timestamp: true,
589592
display_target: true,
590593
display_level: true,
594+
display_executable_name: false,
595+
executable_name: None,
596+
display_process_id: false,
591597
display_thread_id: false,
592598
display_thread_name: false,
593599
display_filename: false,
@@ -608,6 +614,9 @@ impl<F, T> Format<F, T> {
608614
display_target: false,
609615
display_timestamp: self.display_timestamp,
610616
display_level: self.display_level,
617+
display_executable_name: self.display_executable_name,
618+
executable_name: self.executable_name,
619+
display_process_id: self.display_process_id,
611620
display_thread_id: self.display_thread_id,
612621
display_thread_name: self.display_thread_name,
613622
display_filename: self.display_filename,
@@ -647,6 +656,9 @@ impl<F, T> Format<F, T> {
647656
display_target: self.display_target,
648657
display_timestamp: self.display_timestamp,
649658
display_level: self.display_level,
659+
display_executable_name: self.display_executable_name,
660+
executable_name: self.executable_name,
661+
display_process_id: self.display_process_id,
650662
display_thread_id: self.display_thread_id,
651663
display_thread_name: self.display_thread_name,
652664
display_filename: true,
@@ -679,6 +691,9 @@ impl<F, T> Format<F, T> {
679691
display_target: self.display_target,
680692
display_timestamp: self.display_timestamp,
681693
display_level: self.display_level,
694+
display_executable_name: self.display_executable_name,
695+
executable_name: self.executable_name,
696+
display_process_id: self.display_process_id,
682697
display_thread_id: self.display_thread_id,
683698
display_thread_name: self.display_thread_name,
684699
display_filename: self.display_filename,
@@ -708,6 +723,9 @@ impl<F, T> Format<F, T> {
708723
display_target: self.display_target,
709724
display_timestamp: self.display_timestamp,
710725
display_level: self.display_level,
726+
display_executable_name: self.display_executable_name,
727+
executable_name: self.executable_name,
728+
display_process_id: self.display_process_id,
711729
display_thread_id: self.display_thread_id,
712730
display_thread_name: self.display_thread_name,
713731
display_filename: self.display_filename,
@@ -724,6 +742,9 @@ impl<F, T> Format<F, T> {
724742
display_timestamp: false,
725743
display_target: self.display_target,
726744
display_level: self.display_level,
745+
display_executable_name: self.display_executable_name,
746+
executable_name: self.executable_name,
747+
display_process_id: self.display_process_id,
727748
display_thread_id: self.display_thread_id,
728749
display_thread_name: self.display_thread_name,
729750
display_filename: self.display_filename,
@@ -755,6 +776,34 @@ impl<F, T> Format<F, T> {
755776
}
756777
}
757778

779+
/// Sets whether or not the binary name of the process is displayed when
780+
/// formatting events. If executable_name is None, argv\[0\] will be used,
781+
/// otherwise the spcified string will be used.
782+
///
783+
/// [argv\[0\]]: std::env::args
784+
pub fn with_executable_name(
785+
self,
786+
display_executable_name: bool,
787+
executable_name: Option<impl Into<String>>,
788+
) -> Format<F, T> {
789+
Format {
790+
display_executable_name,
791+
executable_name: executable_name.map(Into::into),
792+
..self
793+
}
794+
}
795+
796+
/// Sets whether or not the [process ID] of the current thread is displayed
797+
/// when formatting events.
798+
///
799+
/// [process ID]: std::process::id
800+
pub fn with_process_id(self, display_process_id: bool) -> Format<F, T> {
801+
Format {
802+
display_process_id,
803+
..self
804+
}
805+
}
806+
758807
/// Sets whether or not the [thread ID] of the current thread is displayed
759808
/// when formatting events.
760809
///
@@ -940,6 +989,20 @@ where
940989
self.format_timestamp(&mut writer)?;
941990
self.format_level(*meta.level(), &mut writer)?;
942991

992+
if self.display_executable_name {
993+
if let Some(executable_name) = &self.executable_name {
994+
write!(writer, "{} ", executable_name)?;
995+
} else if let Some(argv0) = std::env::args().next() {
996+
write!(writer, "{} ", argv0)?;
997+
} else {
998+
write!(writer, "<missing_argv[0] ")?;
999+
}
1000+
}
1001+
1002+
if self.display_process_id {
1003+
write!(writer, "PID({}) ", std::process::id())?;
1004+
}
1005+
9431006
if self.display_thread_name {
9441007
let current_thread = std::thread::current();
9451008
match current_thread.name() {
@@ -1067,7 +1130,12 @@ where
10671130

10681131
let dimmed = writer.dimmed();
10691132
if self.display_target {
1070-
write!(writer, "{}{}", dimmed.paint(meta.target()), dimmed.paint(":"))?;
1133+
write!(
1134+
writer,
1135+
"{}{}",
1136+
dimmed.paint(meta.target()),
1137+
dimmed.paint(":")
1138+
)?;
10711139
}
10721140

10731141
if self.display_filename {
@@ -1662,6 +1730,8 @@ pub(super) mod test {
16621730
.without_time()
16631731
.with_level(false)
16641732
.with_target(false)
1733+
.with_executable_name(false, None::<&str>)
1734+
.with_process_id(false)
16651735
.with_thread_ids(false)
16661736
.with_thread_names(false);
16671737
#[cfg(feature = "ansi")]
@@ -1777,6 +1847,50 @@ pub(super) mod test {
17771847
assert_info_hello(subscriber, make_writer, expected);
17781848
}
17791849

1850+
#[test]
1851+
fn with_automatic_executable_name() {
1852+
let make_writer = MockMakeWriter::default();
1853+
let subscriber = crate::fmt::Collector::builder()
1854+
.with_writer(make_writer.clone())
1855+
.with_executable_name(true, None::<&str>)
1856+
.with_ansi(false)
1857+
.with_timer(MockTime);
1858+
let expected = format!(
1859+
"fake time INFO {} tracing_subscriber::fmt::format::test: hello\n",
1860+
std::env::args().next().unwrap()
1861+
);
1862+
1863+
assert_info_hello(subscriber, make_writer, &expected);
1864+
}
1865+
1866+
#[test]
1867+
fn with_manual_executable_name() {
1868+
let make_writer = MockMakeWriter::default();
1869+
let subscriber = crate::fmt::Collector::builder()
1870+
.with_writer(make_writer.clone())
1871+
.with_executable_name(true, Some("a_nice_rust_binary"))
1872+
.with_ansi(false)
1873+
.with_timer(MockTime);
1874+
let expected =
1875+
"fake time INFO a_nice_rust_binary tracing_subscriber::fmt::format::test: hello\n";
1876+
1877+
assert_info_hello(subscriber, make_writer, expected);
1878+
}
1879+
1880+
#[test]
1881+
fn with_process_id() {
1882+
let make_writer = MockMakeWriter::default();
1883+
let subscriber = crate::fmt::Collector::builder()
1884+
.with_writer(make_writer.clone())
1885+
.with_process_id(true)
1886+
.with_ansi(false)
1887+
.with_timer(MockTime);
1888+
let expected =
1889+
"fake time INFO PID(NUMERIC) tracing_subscriber::fmt::format::test: hello\n";
1890+
1891+
assert_info_hello_ignore_numeric(subscriber, make_writer, expected);
1892+
}
1893+
17801894
#[test]
17811895
fn with_thread_ids() {
17821896
let make_writer = MockMakeWriter::default();

tracing-subscriber/src/fmt/mod.rs

+32
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,38 @@ where
703703
}
704704
}
705705

706+
/// Sets whether or not the binary name of the process is displayed when
707+
/// formatting events. If executable_name is None, argv\[0\] will be used,
708+
/// otherwise the spcified string will be used.
709+
///
710+
/// [argv\[0\]]: std::env::args
711+
pub fn with_executable_name(
712+
self,
713+
display_executable_name: bool,
714+
executable_name: Option<impl Into<String>>,
715+
) -> CollectorBuilder<N, format::Format<L, T>, F, W> {
716+
CollectorBuilder {
717+
inner: self
718+
.inner
719+
.with_executable_name(display_executable_name, executable_name),
720+
..self
721+
}
722+
}
723+
724+
/// Sets whether or not the [process ID] of the current thread is displayed
725+
/// when formatting events.
726+
///
727+
/// [process ID]: std::process::id
728+
pub fn with_process_id(
729+
self,
730+
display_process_id: bool,
731+
) -> CollectorBuilder<N, format::Format<L, T>, F, W> {
732+
CollectorBuilder {
733+
inner: self.inner.with_process_id(display_process_id),
734+
..self
735+
}
736+
}
737+
706738
/// Sets whether or not the [name] of the current thread is displayed
707739
/// when formatting events.
708740
///

0 commit comments

Comments
 (0)