Skip to content

Commit 13c5c56

Browse files
committed
feat(subscriber): Add with_span_list implementation for all standard formats.
1 parent c297a37 commit 13c5c56

File tree

5 files changed

+109
-78
lines changed

5 files changed

+109
-78
lines changed

tracing-subscriber/src/fmt/fmt_layer.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,15 @@ where
484484
}
485485
}
486486

487+
/// Sets whether or not the formatter will include a list (from root to leaf)
488+
/// of all currently entered spans in formatted events.
489+
pub fn with_span_list(self, display_span_list: bool) -> Self {
490+
Layer {
491+
fmt_event: self.fmt_event.with_span_list(display_span_list),
492+
..self
493+
}
494+
}
495+
487496
/// Sets whether or not an event's target is displayed.
488497
pub fn with_target(self, display_target: bool) -> Layer<S, N, format::Format<L, T>, W> {
489498
Layer {
@@ -643,21 +652,6 @@ impl<S, T, W> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> {
643652
..self
644653
}
645654
}
646-
647-
/// Sets whether or not the formatter will include a list (from root to leaf)
648-
/// of all currently entered spans in formatted events.
649-
///
650-
/// See [`format::Json`][super::format::Json]
651-
pub fn with_span_list(
652-
self,
653-
display_span_list: bool,
654-
) -> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> {
655-
Layer {
656-
fmt_event: self.fmt_event.with_span_list(display_span_list),
657-
fmt_fields: format::JsonFields::new(),
658-
..self
659-
}
660-
}
661655
}
662656

663657
impl<S, N, E, W> Layer<S, N, E, W> {

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

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ use tracing_log::NormalizeEvent;
9292
pub struct Json {
9393
pub(crate) flatten_event: bool,
9494
pub(crate) display_current_span: bool,
95-
pub(crate) display_span_list: bool,
9695
}
9796

9897
impl Json {
@@ -105,12 +104,6 @@ impl Json {
105104
pub fn with_current_span(&mut self, display_current_span: bool) {
106105
self.display_current_span = display_current_span;
107106
}
108-
109-
/// If set to `false`, formatted events won't contain a list of all currently
110-
/// entered spans. Spans are logged in a list from root to leaf.
111-
pub fn with_span_list(&mut self, display_span_list: bool) {
112-
self.display_span_list = display_span_list;
113-
}
114107
}
115108

116109
struct SerializableContext<'a, 'b, Span, N>(
@@ -252,8 +245,7 @@ where
252245

253246
let format_field_marker: std::marker::PhantomData<N> = std::marker::PhantomData;
254247

255-
let current_span = if self.format.display_current_span || self.format.display_span_list
256-
{
248+
let current_span = if self.format.display_current_span || self.display_span_list {
257249
event
258250
.parent()
259251
.and_then(|id| ctx.span(id))
@@ -296,7 +288,7 @@ where
296288
}
297289
}
298290

299-
if self.format.display_span_list && current_span.is_some() {
291+
if self.display_span_list && current_span.is_some() {
300292
serializer.serialize_entry(
301293
"spans",
302294
&SerializableContext(&ctx.ctx, format_field_marker),
@@ -336,7 +328,6 @@ impl Default for Json {
336328
Json {
337329
flatten_event: false,
338330
display_current_span: true,
339-
display_span_list: true,
340331
}
341332
}
342333
}

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

Lines changed: 85 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ pub struct Format<F = Full, T = SystemTime> {
412412
pub(crate) display_thread_name: bool,
413413
pub(crate) display_filename: bool,
414414
pub(crate) display_line_number: bool,
415+
pub(crate) display_span_list: bool,
415416
}
416417

417418
// === impl Writer ===
@@ -604,6 +605,7 @@ impl Default for Format<Full, SystemTime> {
604605
display_thread_name: false,
605606
display_filename: false,
606607
display_line_number: false,
608+
display_span_list: true,
607609
}
608610
}
609611
}
@@ -624,6 +626,7 @@ impl<F, T> Format<F, T> {
624626
display_thread_name: self.display_thread_name,
625627
display_filename: self.display_filename,
626628
display_line_number: self.display_line_number,
629+
display_span_list: self.display_line_number,
627630
}
628631
}
629632

@@ -663,6 +666,7 @@ impl<F, T> Format<F, T> {
663666
display_thread_name: self.display_thread_name,
664667
display_filename: true,
665668
display_line_number: true,
669+
display_span_list: self.display_line_number,
666670
}
667671
}
668672

@@ -694,6 +698,7 @@ impl<F, T> Format<F, T> {
694698
display_thread_name: self.display_thread_name,
695699
display_filename: self.display_filename,
696700
display_line_number: self.display_line_number,
701+
display_span_list: self.display_line_number,
697702
}
698703
}
699704

@@ -723,6 +728,7 @@ impl<F, T> Format<F, T> {
723728
display_thread_name: self.display_thread_name,
724729
display_filename: self.display_filename,
725730
display_line_number: self.display_line_number,
731+
display_span_list: self.display_line_number,
726732
}
727733
}
728734

@@ -739,6 +745,7 @@ impl<F, T> Format<F, T> {
739745
display_thread_name: self.display_thread_name,
740746
display_filename: self.display_filename,
741747
display_line_number: self.display_line_number,
748+
display_span_list: self.display_line_number,
742749
}
743750
}
744751

@@ -820,6 +827,15 @@ impl<F, T> Format<F, T> {
820827
.with_file(display_location)
821828
}
822829

830+
/// If set to `false`, formatted events won't contain a list of all currently
831+
/// entered spans. Spans are logged in a list from root to leaf.
832+
pub fn with_span_list(self, display_span_list: bool) -> Self {
833+
Format {
834+
display_span_list,
835+
..self
836+
}
837+
}
838+
823839
#[inline]
824840
fn format_timestamp(&self, writer: &mut Writer<'_>) -> fmt::Result
825841
where
@@ -887,17 +903,6 @@ impl<T> Format<Json, T> {
887903
self.format.with_current_span(display_current_span);
888904
self
889905
}
890-
891-
/// Sets whether or not the formatter will include a list (from root to
892-
/// leaf) of all currently entered spans in formatted events.
893-
///
894-
/// See [`format::Json`][Json]
895-
#[cfg(feature = "json")]
896-
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
897-
pub fn with_span_list(mut self, display_span_list: bool) -> Format<Json, T> {
898-
self.format.with_span_list(display_span_list);
899-
self
900-
}
901906
}
902907

903908
impl<S, N, T> FormatEvent<S, N> for Format<Full, T>
@@ -963,25 +968,34 @@ where
963968

964969
let dimmed = writer.dimmed();
965970

966-
if let Some(scope) = ctx.event_scope() {
971+
if let Some(mut scope) = ctx.event_scope() {
967972
let bold = writer.bold();
968-
969-
let mut seen = false;
970-
971-
for span in scope.from_root() {
973+
if self.display_span_list {
974+
let scope_from_root = scope.from_root();
975+
let mut seen = false;
976+
for span in scope_from_root {
977+
write!(writer, "{}", bold.paint(span.metadata().name()))?;
978+
seen = true;
979+
let ext = span.extensions();
980+
if let Some(fields) = &ext.get::<FormattedFields<N>>() {
981+
if !fields.is_empty() {
982+
write!(writer, "{}{}{}", bold.paint("{"), fields, bold.paint("}"))?;
983+
}
984+
}
985+
write!(writer, "{}", dimmed.paint(":"))?;
986+
}
987+
if seen {
988+
writer.write_char(' ')?;
989+
}
990+
} else if let Some(span) = scope.next() {
972991
write!(writer, "{}", bold.paint(span.metadata().name()))?;
973-
seen = true;
974-
975992
let ext = span.extensions();
976993
if let Some(fields) = &ext.get::<FormattedFields<N>>() {
977994
if !fields.is_empty() {
978995
write!(writer, "{}{}{}", bold.paint("{"), fields, bold.paint("}"))?;
979996
}
980997
}
981998
write!(writer, "{}", dimmed.paint(":"))?;
982-
}
983-
984-
if seen {
985999
writer.write_char(' ')?;
9861000
}
9871001
};
@@ -1092,11 +1106,16 @@ where
10921106
let fmt_ctx = {
10931107
#[cfg(feature = "ansi")]
10941108
{
1095-
FmtCtx::new(ctx, event.parent(), writer.has_ansi_escapes())
1109+
FmtCtx::new(
1110+
ctx,
1111+
event.parent(),
1112+
self.display_span_list,
1113+
writer.has_ansi_escapes(),
1114+
)
10961115
}
10971116
#[cfg(not(feature = "ansi"))]
10981117
{
1099-
FmtCtx::new(&ctx, event.parent())
1118+
FmtCtx::new(&ctx, event.parent(), self.display_span_list)
11001119
}
11011120
};
11021121
write!(writer, "{}", fmt_ctx)?;
@@ -1144,11 +1163,20 @@ where
11441163

11451164
ctx.format_fields(writer.by_ref(), event)?;
11461165

1147-
for span in ctx
1148-
.event_scope()
1149-
.into_iter()
1150-
.flat_map(crate::registry::Scope::from_root)
1151-
{
1166+
if self.display_span_list {
1167+
for span in ctx
1168+
.event_scope()
1169+
.into_iter()
1170+
.flat_map(crate::registry::Scope::from_root)
1171+
{
1172+
let exts = span.extensions();
1173+
if let Some(fields) = exts.get::<FormattedFields<N>>() {
1174+
if !fields.is_empty() {
1175+
write!(writer, " {}", dimmed.paint(&fields.fields))?;
1176+
}
1177+
}
1178+
}
1179+
} else if let Some(span) = ctx.event_scope().as_mut().and_then(|scope| scope.next()) {
11521180
let exts = span.extensions();
11531181
if let Some(fields) = exts.get::<FormattedFields<N>>() {
11541182
if !fields.is_empty() {
@@ -1347,6 +1375,7 @@ impl Display for ErrorSourceList<'_> {
13471375
struct FmtCtx<'a, S, N> {
13481376
ctx: &'a FmtContext<'a, S, N>,
13491377
span: Option<&'a span::Id>,
1378+
display_span_list: bool,
13501379
#[cfg(feature = "ansi")]
13511380
ansi: bool,
13521381
}
@@ -1360,14 +1389,28 @@ where
13601389
pub(crate) fn new(
13611390
ctx: &'a FmtContext<'_, S, N>,
13621391
span: Option<&'a span::Id>,
1392+
display_span_list: bool,
13631393
ansi: bool,
13641394
) -> Self {
1365-
Self { ctx, span, ansi }
1395+
Self {
1396+
ctx,
1397+
span,
1398+
ansi,
1399+
display_span_list,
1400+
}
13661401
}
13671402

13681403
#[cfg(not(feature = "ansi"))]
1369-
pub(crate) fn new(ctx: &'a FmtContext<'_, S, N>, span: Option<&'a span::Id>) -> Self {
1370-
Self { ctx, span }
1404+
pub(crate) fn new(
1405+
ctx: &'a FmtContext<'_, S, N>,
1406+
span: Option<&'a span::Id>,
1407+
display_span_list: bool,
1408+
) -> Self {
1409+
Self {
1410+
ctx,
1411+
span,
1412+
display_span_list,
1413+
}
13711414
}
13721415

13731416
fn bold(&self) -> Style {
@@ -1396,14 +1439,19 @@ where
13961439
.and_then(|id| self.ctx.ctx.span(id))
13971440
.or_else(|| self.ctx.ctx.lookup_current());
13981441

1399-
let scope = span.into_iter().flat_map(|span| span.scope().from_root());
1442+
if self.display_span_list {
1443+
let scope = span.into_iter().flat_map(|span| span.scope().from_root());
14001444

1401-
for span in scope {
1402-
seen = true;
1403-
write!(f, "{}:", bold.paint(span.metadata().name()))?;
1404-
}
1445+
for span in scope {
1446+
seen = true;
1447+
write!(f, "{}:", bold.paint(span.metadata().name()))?;
1448+
}
14051449

1406-
if seen {
1450+
if seen {
1451+
f.write_char(' ')?;
1452+
}
1453+
} else if let Some(span) = span.iter().next() {
1454+
write!(f, "{}:", bold.paint(span.metadata().name()))?;
14071455
f.write_char(' ')?;
14081456
}
14091457
Ok(())

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,9 @@ where
327327
if !fields.is_empty() {
328328
write!(writer, " {} {}", dimmed.paint("with"), fields)?;
329329
}
330+
if !self.display_span_list {
331+
break;
332+
}
330333
writer.write_char('\n')?;
331334
}
332335

@@ -478,7 +481,7 @@ impl field::Visit for PrettyVisitor<'_> {
478481
"message" => {
479482
// Escape ANSI characters to prevent malicious patterns (e.g., terminal injection attacks)
480483
self.write_padded(&format_args!("{}{:?}", self.style.prefix(), Escape(value)))
481-
},
484+
}
482485
// Skip fields that are actually log metadata that have already been handled
483486
#[cfg(feature = "tracing-log")]
484487
name if name.starts_with("log.") => self.result = Ok(()),

tracing-subscriber/src/fmt/mod.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,15 @@ where
615615
}
616616
}
617617

618+
/// Sets whether or not the subscriber being built will include a list (from
619+
/// root to leaf) of all currently entered spans in formatted events.
620+
pub fn with_span_list(self, display_span_list: bool) -> Self {
621+
SubscriberBuilder {
622+
inner: self.inner.with_span_list(display_span_list),
623+
..self
624+
}
625+
}
626+
618627
/// Sets whether or not the formatter emits ANSI terminal escape codes
619628
/// for colors and other text formatting.
620629
///
@@ -808,20 +817,6 @@ impl<T, F, W> SubscriberBuilder<format::JsonFields, format::Format<format::Json,
808817
inner: self.inner.with_current_span(display_current_span),
809818
}
810819
}
811-
812-
/// Sets whether or not the JSON subscriber being built will include a list (from
813-
/// root to leaf) of all currently entered spans in formatted events.
814-
///
815-
/// See [`format::Json`] for details.
816-
pub fn with_span_list(
817-
self,
818-
display_span_list: bool,
819-
) -> SubscriberBuilder<format::JsonFields, format::Format<format::Json, T>, F, W> {
820-
SubscriberBuilder {
821-
filter: self.filter,
822-
inner: self.inner.with_span_list(display_span_list),
823-
}
824-
}
825820
}
826821

827822
#[cfg(feature = "env-filter")]

0 commit comments

Comments
 (0)