Skip to content

Commit aa64320

Browse files
committed
subscriber: write format_event errors to Writer, update SubscriberBuilder
Update the error-handling logic when calling `format_event` to write the error message to the Writer. Only if that fails do we write to stderr. Define new method `SubscriberBuilder::with_silence_errors(bool)` so that a user may disable this behavior. Enabled by default. Add unit tests for both `silence_errors=true` and `false`.
1 parent c725c8a commit aa64320

File tree

2 files changed

+108
-3
lines changed

2 files changed

+108
-3
lines changed

tracing-subscriber/src/fmt/fmt_layer.rs

+95-3
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub struct Layer<
7070
fmt_event: E,
7171
fmt_span: format::FmtSpanConfig,
7272
is_ansi: bool,
73+
silence_errors: bool,
7374
_inner: PhantomData<fn(S)>,
7475
}
7576

@@ -119,6 +120,7 @@ where
119120
fmt_span: self.fmt_span,
120121
make_writer: self.make_writer,
121122
is_ansi: self.is_ansi,
123+
silence_errors: self.silence_errors,
122124
_inner: self._inner,
123125
}
124126
}
@@ -148,6 +150,7 @@ where
148150
fmt_span: self.fmt_span,
149151
make_writer: self.make_writer,
150152
is_ansi: self.is_ansi,
153+
silence_errors: self.silence_errors,
151154
_inner: self._inner,
152155
}
153156
}
@@ -180,6 +183,7 @@ impl<S, N, E, W> Layer<S, N, E, W> {
180183
fmt_event: self.fmt_event,
181184
fmt_span: self.fmt_span,
182185
is_ansi: self.is_ansi,
186+
silence_errors: self.silence_errors,
183187
make_writer,
184188
_inner: self._inner,
185189
}
@@ -263,6 +267,7 @@ impl<S, N, E, W> Layer<S, N, E, W> {
263267
fmt_event: self.fmt_event,
264268
fmt_span: self.fmt_span,
265269
is_ansi: self.is_ansi,
270+
silence_errors: self.silence_errors,
266271
make_writer: TestWriter::default(),
267272
_inner: self._inner,
268273
}
@@ -278,6 +283,14 @@ impl<S, N, E, W> Layer<S, N, E, W> {
278283
}
279284
}
280285

286+
/// Whether to write errors to the Writer, or ignore them.
287+
pub fn with_silence_errors(self, silence_errors: bool) -> Self {
288+
Self {
289+
silence_errors,
290+
..self
291+
}
292+
}
293+
281294
/// Updates the [`MakeWriter`] by applying a function to the existing [`MakeWriter`].
282295
///
283296
/// This sets the [`MakeWriter`] that the layer being built will use to write events.
@@ -306,6 +319,7 @@ impl<S, N, E, W> Layer<S, N, E, W> {
306319
fmt_event: self.fmt_event,
307320
fmt_span: self.fmt_span,
308321
is_ansi: self.is_ansi,
322+
silence_errors: self.silence_errors,
309323
make_writer: f(self.make_writer),
310324
_inner: self._inner,
311325
}
@@ -337,6 +351,7 @@ where
337351
fmt_span: self.fmt_span,
338352
make_writer: self.make_writer,
339353
is_ansi: self.is_ansi,
354+
silence_errors: self.silence_errors,
340355
_inner: self._inner,
341356
}
342357
}
@@ -349,6 +364,7 @@ where
349364
fmt_span: self.fmt_span.without_time(),
350365
make_writer: self.make_writer,
351366
is_ansi: self.is_ansi,
367+
silence_errors: self.silence_errors,
352368
_inner: self._inner,
353369
}
354370
}
@@ -477,6 +493,7 @@ where
477493
fmt_span: self.fmt_span,
478494
make_writer: self.make_writer,
479495
is_ansi: self.is_ansi,
496+
silence_errors: self.silence_errors,
480497
_inner: self._inner,
481498
}
482499
}
@@ -491,6 +508,7 @@ where
491508
fmt_span: self.fmt_span,
492509
make_writer: self.make_writer,
493510
is_ansi: self.is_ansi,
511+
silence_errors: self.silence_errors,
494512
_inner: self._inner,
495513
}
496514
}
@@ -521,6 +539,7 @@ where
521539
make_writer: self.make_writer,
522540
// always disable ANSI escapes in JSON mode!
523541
is_ansi: false,
542+
silence_errors: self.silence_errors,
524543
_inner: self._inner,
525544
}
526545
}
@@ -587,6 +606,7 @@ impl<S, N, E, W> Layer<S, N, E, W> {
587606
fmt_span: self.fmt_span,
588607
make_writer: self.make_writer,
589608
is_ansi: self.is_ansi,
609+
silence_errors: self.silence_errors,
590610
_inner: self._inner,
591611
}
592612
}
@@ -617,6 +637,7 @@ impl<S, N, E, W> Layer<S, N, E, W> {
617637
fmt_span: self.fmt_span,
618638
make_writer: self.make_writer,
619639
is_ansi: self.is_ansi,
640+
silence_errors: self.silence_errors,
620641
_inner: self._inner,
621642
}
622643
}
@@ -630,6 +651,7 @@ impl<S> Default for Layer<S> {
630651
fmt_span: format::FmtSpanConfig::default(),
631652
make_writer: io::stdout,
632653
is_ansi: cfg!(feature = "ansi"),
654+
silence_errors: false,
633655
_inner: PhantomData,
634656
}
635657
}
@@ -749,6 +771,11 @@ where
749771
{
750772
fields.was_ansi = self.is_ansi;
751773
extensions.insert(fields);
774+
} else {
775+
eprintln!(
776+
"[tracing-subscriber] Unable to format the following event, ignoring: {:?}",
777+
attrs
778+
);
752779
}
753780
}
754781

@@ -895,9 +922,20 @@ where
895922
.is_ok()
896923
{
897924
let mut writer = self.make_writer.make_writer_for(event.metadata());
898-
let _ = io::Write::write_all(&mut writer, buf.as_bytes());
899-
} else {
900-
eprintln!("[tracing-subscriber] Unable to format the following event: {:?}", event);
925+
let res = io::Write::write_all(&mut writer, buf.as_bytes());
926+
if !self.silence_errors {
927+
if let Err(e) = res {
928+
eprintln!("Unable to write an event to the Writer for this Subscriber! Error: {}\n", e);
929+
}
930+
}
931+
} else if !self.silence_errors {
932+
let err_msg = format!("Unable to format the following event. Name: {}; Fields: {:?}\n",
933+
event.metadata().name(), event.fields());
934+
let mut writer = self.make_writer.make_writer_for(event.metadata());
935+
let res = io::Write::write_all(&mut writer, err_msg.as_bytes());
936+
if let Err(e) = res {
937+
eprintln!("Unable to write an \"event formatting error\" to the Writer for this Subscriber! Error: {}\n", e);
938+
}
901939
}
902940

903941
buf.clear();
@@ -1194,6 +1232,60 @@ mod test {
11941232
re.replace_all(s.as_str(), "timing").to_string()
11951233
}
11961234

1235+
#[test]
1236+
fn format_error_print_to_stderr() {
1237+
struct AlwaysError;
1238+
1239+
impl std::fmt::Debug for AlwaysError {
1240+
fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1241+
Err(std::fmt::Error)
1242+
}
1243+
}
1244+
1245+
let make_writer = MockMakeWriter::default();
1246+
let subscriber = crate::fmt::Subscriber::builder()
1247+
.with_writer(make_writer.clone())
1248+
.with_level(false)
1249+
.with_ansi(false)
1250+
.with_timer(MockTime)
1251+
.finish();
1252+
1253+
with_default(subscriber, || {
1254+
tracing::info!(?AlwaysError);
1255+
});
1256+
let actual = sanitize_timings(make_writer.get_string());
1257+
1258+
// Only assert the start because the line number and callsite may change.
1259+
let expected = "Unable to format the following event. Name: event tracing-subscriber/src/fmt/fmt_layer.rs:";
1260+
assert!(actual.as_str().starts_with(expected));
1261+
}
1262+
1263+
#[test]
1264+
fn format_error_ignore_if_silence_errors_is_true() {
1265+
struct AlwaysError;
1266+
1267+
impl std::fmt::Debug for AlwaysError {
1268+
fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1269+
Err(std::fmt::Error)
1270+
}
1271+
}
1272+
1273+
let make_writer = MockMakeWriter::default();
1274+
let subscriber = crate::fmt::Subscriber::builder()
1275+
.with_writer(make_writer.clone())
1276+
.with_level(false)
1277+
.with_ansi(false)
1278+
.with_timer(MockTime)
1279+
.with_silence_errors(true)
1280+
.finish();
1281+
1282+
with_default(subscriber, || {
1283+
tracing::info!(?AlwaysError);
1284+
});
1285+
let actual = sanitize_timings(make_writer.get_string());
1286+
assert_eq!("", actual.as_str());
1287+
}
1288+
11971289
#[test]
11981290
fn synthesize_span_none() {
11991291
let make_writer = MockMakeWriter::default();

tracing-subscriber/src/fmt/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,19 @@ where
615615
}
616616
}
617617

618+
/// Whether to write errors to the Writer, or ignore them.
619+
///
620+
/// An error in this case refers to errors which may occur within the
621+
/// Subscriber implementation itself, or in code that it depends on.
622+
///
623+
/// It does not refer to traces set to the level of Error.
624+
pub fn with_silence_errors(self, silence_errors: bool) -> SubscriberBuilder<N, format::Format<L, T>, F, W> {
625+
SubscriberBuilder {
626+
inner: self.inner.with_silence_errors(silence_errors),
627+
..self
628+
}
629+
}
630+
618631
/// Sets whether or not an event's target is displayed.
619632
pub fn with_target(
620633
self,

0 commit comments

Comments
 (0)