Skip to content

Instantly share code, notes, and snippets.

@radix
Last active April 25, 2025 15:10
Show Gist options
  • Save radix/8a673a4c36512560a1f132dbf634508e to your computer and use it in GitHub Desktop.
Save radix/8a673a4c36512560a1f132dbf634508e to your computer and use it in GitHub Desktop.
diff --git a/tracing-subscriber/src/fmt/format/json.rs b/tracing-subscriber/src/fmt/format/json.rs
index 3ef0fcd6..5f63d40f 100644
--- a/tracing-subscriber/src/fmt/format/json.rs
+++ b/tracing-subscriber/src/fmt/format/json.rs
@@ -530,6 +530,20 @@ impl field::Visit for JsonVisitor<'_> {
.insert(field.name(), serde_json::Value::from(value));
}
+ #[cfg(feature = "std")]
+ fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) {
+ panic!("Hello? Is this even being called?");
+ // TODO: Switch to https://github.com/rust-lang/rust/issues/58520 when it's stable
+ let mut error_chain = vec![];
+ let mut current_error: Option<&(dyn std::error::Error + 'static)> = Some(value);
+ while let Some(err) = current_error {
+ error_chain.push(serde_json::Value::from(format!("{:?}", err)));
+ current_error = err.source();
+ }
+ let sources = serde_json::Value::Array(error_chain);
+ self.values.insert(field.name(), sources);
+ }
+
fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
match field.name() {
// Skip fields that are actually log metadata that have already been handled
@@ -827,6 +841,41 @@ mod test {
});
}
+ /// The chain of error sources is included in the result.
+ #[test]
+ fn error_chain() {
+ let expected = "{}";
+ let subscriber = subscriber()
+ .flatten_event(false)
+ .with_current_span(true)
+ .with_span_list(true);
+ #[derive(Debug)]
+ struct Error {
+ source: core::num::ParseIntError,
+ }
+ impl core::error::Error for Error {
+ fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
+ Some(&self.source)
+ }
+ }
+ impl core::fmt::Display for Error {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ write!(f, "Hello World")?;
+ Ok(())
+ }
+ }
+
+ let result: Result<u32, core::num::ParseIntError> = "abc".parse();
+ let err = Error {
+ source: result.unwrap_err(),
+ };
+ test_json(expected, subscriber, || {
+ tracing::error!(
+ error = &err as &(dyn std::error::Error + 'static),
+ "error json test"
+ );
+ });
+ }
+
fn parse_as_json(buffer: &MockMakeWriter) -> serde_json::Value {
let buf = String::from_utf8(buffer.buf().to_vec()).unwrap();
let json = buf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment