@@ -9,6 +9,7 @@ use crate::{
99} ;
1010use serde:: ser:: { SerializeMap , Serializer as _} ;
1111use serde_json:: Serializer ;
12+ use std:: borrow:: Cow ;
1213use std:: {
1314 collections:: BTreeMap ,
1415 fmt:: { self , Write } ,
@@ -405,7 +406,7 @@ impl<'a> FormatFields<'a> for JsonFields {
405406 // then, we could store fields as JSON values, and add to them
406407 // without having to parse and re-serialize.
407408 let mut new = String :: new ( ) ;
408- let map: BTreeMap < & ' _ str , serde_json:: Value > =
409+ let map: BTreeMap < Cow < ' _ , str > , serde_json:: Value > =
409410 serde_json:: from_str ( current) . map_err ( |_| fmt:: Error ) ?;
410411 let mut v = JsonVisitor :: new ( & mut new) ;
411412 v. values = map;
@@ -422,7 +423,7 @@ impl<'a> FormatFields<'a> for JsonFields {
422423/// [visitor]: crate::field::Visit
423424/// [`MakeVisitor`]: crate::field::MakeVisitor
424425pub struct JsonVisitor < ' a > {
425- values : BTreeMap < & ' a str , serde_json:: Value > ,
426+ values : BTreeMap < Cow < ' a , str > , serde_json:: Value > ,
426427 writer : & ' a mut dyn Write ,
427428}
428429
@@ -460,7 +461,7 @@ impl crate::field::VisitOutput<fmt::Result> for JsonVisitor<'_> {
460461 let mut ser_map = serializer. serialize_map ( None ) ?;
461462
462463 for ( k, v) in self . values {
463- ser_map. serialize_entry ( k, & v) ?;
464+ ser_map. serialize_entry ( & * k, & v) ?;
464465 }
465466
466467 ser_map. end ( )
@@ -498,36 +499,57 @@ impl field::Visit for JsonVisitor<'_> {
498499 /// Visit a double precision floating point value.
499500 fn record_f64 ( & mut self , field : & Field , value : f64 ) {
500501 self . values
501- . insert ( field. name ( ) , serde_json:: Value :: from ( value) ) ;
502+ . insert ( field. name ( ) . into ( ) , serde_json:: Value :: from ( value) ) ;
502503 }
503504
504505 /// Visit a signed 64-bit integer value.
505506 fn record_i64 ( & mut self , field : & Field , value : i64 ) {
506507 self . values
507- . insert ( field. name ( ) , serde_json:: Value :: from ( value) ) ;
508+ . insert ( field. name ( ) . into ( ) , serde_json:: Value :: from ( value) ) ;
508509 }
509510
510511 /// Visit an unsigned 64-bit integer value.
511512 fn record_u64 ( & mut self , field : & Field , value : u64 ) {
512513 self . values
513- . insert ( field. name ( ) , serde_json:: Value :: from ( value) ) ;
514+ . insert ( field. name ( ) . into ( ) , serde_json:: Value :: from ( value) ) ;
514515 }
515516
516517 /// Visit a boolean value.
517518 fn record_bool ( & mut self , field : & Field , value : bool ) {
518519 self . values
519- . insert ( field. name ( ) , serde_json:: Value :: from ( value) ) ;
520+ . insert ( field. name ( ) . into ( ) , serde_json:: Value :: from ( value) ) ;
520521 }
521522
522523 /// Visit a string value.
523524 fn record_str ( & mut self , field : & Field , value : & str ) {
524525 self . values
525- . insert ( field. name ( ) , serde_json:: Value :: from ( value) ) ;
526+ . insert ( field. name ( ) . into ( ) , serde_json:: Value :: from ( value) ) ;
526527 }
527528
528529 fn record_bytes ( & mut self , field : & Field , value : & [ u8 ] ) {
529530 self . values
530- . insert ( field. name ( ) , serde_json:: Value :: from ( value) ) ;
531+ . insert ( field. name ( ) . into ( ) , serde_json:: Value :: from ( value) ) ;
532+ }
533+
534+ fn record_error ( & mut self , field : & Field , value : & ( dyn std:: error:: Error + ' static ) ) {
535+ self . values . insert (
536+ field. name ( ) . into ( ) ,
537+ serde_json:: Value :: from ( value. to_string ( ) ) ,
538+ ) ;
539+
540+ if let Some ( source) = value. source ( ) {
541+ let mut sources = Vec :: new ( ) ;
542+ let mut curr = Some ( source) ;
543+ while let Some ( curr_err) = curr {
544+ sources. push ( serde_json:: Value :: from ( curr_err. to_string ( ) ) ) ;
545+ curr = curr_err. source ( ) ;
546+ }
547+
548+ self . values . insert (
549+ format ! ( "{}.sources" , field. name( ) ) . into ( ) ,
550+ serde_json:: Value :: Array ( sources) ,
551+ ) ;
552+ }
531553 }
532554
533555 fn record_debug ( & mut self , field : & Field , value : & dyn fmt:: Debug ) {
@@ -536,12 +558,14 @@ impl field::Visit for JsonVisitor<'_> {
536558 #[ cfg( feature = "tracing-log" ) ]
537559 name if name. starts_with ( "log." ) => ( ) ,
538560 name if name. starts_with ( "r#" ) => {
539- self . values
540- . insert ( & name[ 2 ..] , serde_json:: Value :: from ( format ! ( "{:?}" , value) ) ) ;
561+ self . values . insert (
562+ ( & name[ 2 ..] ) . into ( ) ,
563+ serde_json:: Value :: from ( format ! ( "{:?}" , value) ) ,
564+ ) ;
541565 }
542566 name => {
543567 self . values
544- . insert ( name, serde_json:: Value :: from ( format ! ( "{:?}" , value) ) ) ;
568+ . insert ( name. into ( ) , serde_json:: Value :: from ( format ! ( "{:?}" , value) ) ) ;
545569 }
546570 } ;
547571 }
@@ -827,6 +851,83 @@ mod test {
827851 } ) ;
828852 }
829853
854+ #[ test]
855+ fn json_field_record_error ( ) {
856+ let buffer = MockMakeWriter :: default ( ) ;
857+ let subscriber = crate :: fmt ( )
858+ . json ( )
859+ . with_writer ( buffer. clone ( ) )
860+ . with_span_events ( FmtSpan :: NEW )
861+ . finish ( ) ;
862+
863+ #[ derive( Debug ) ]
864+ struct Error {
865+ message : & ' static str ,
866+ source : Option < Box < Error > > ,
867+ }
868+
869+ impl std:: fmt:: Display for Error {
870+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
871+ write ! ( f, "{}" , self . message)
872+ }
873+ }
874+
875+ impl std:: error:: Error for Error {
876+ fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
877+ self . source . as_ref ( ) . map ( |e| e. as_ref ( ) as _ )
878+ }
879+ }
880+
881+ let error = Error {
882+ message : "outer" ,
883+ source : Some (
884+ Error {
885+ message : "middle" ,
886+ source : Some (
887+ Error {
888+ message : "inner" ,
889+ source : None ,
890+ }
891+ . into ( ) ,
892+ ) ,
893+ }
894+ . into ( ) ,
895+ ) ,
896+ } ;
897+
898+ with_default ( subscriber, || {
899+ // Event: `tracing_serde::SerdeMapVisitor`
900+ {
901+ tracing:: info!( error = & error as & dyn std:: error:: Error , "event" ) ;
902+ let event = parse_as_json ( & buffer) ;
903+
904+ println ! ( "event {:#?}" , event) ;
905+
906+ assert_eq ! ( event[ "fields" ] [ "message" ] , "event" ) ;
907+ assert_eq ! ( event[ "fields" ] [ "error" ] , "outer" ) ;
908+ assert_eq ! (
909+ event[ "fields" ] [ "error.sources" ] . as_array( ) . unwrap( ) . len( ) ,
910+ 2
911+ ) ;
912+ assert_eq ! ( event[ "fields" ] [ "error.sources" ] [ 0 ] , "middle" ) ;
913+ assert_eq ! ( event[ "fields" ] [ "error.sources" ] [ 1 ] , "inner" ) ;
914+ }
915+
916+ // Span: `tracing_subscriber::fmt::json::JsonVisitor`
917+ {
918+ let _span =
919+ tracing:: info_span!( "parent_span" , error = & error as & dyn std:: error:: Error ) ;
920+ let event = parse_as_json ( & buffer) ;
921+
922+ assert_eq ! ( event[ "span" ] [ "name" ] , "parent_span" ) ;
923+ assert_eq ! ( event[ "span" ] [ "error" ] , "outer" ) ;
924+ assert_eq ! ( event[ "span" ] [ "error.sources" ] . as_array( ) . unwrap( ) . len( ) , 2 ) ;
925+ assert_eq ! ( event[ "span" ] [ "error.sources" ] [ 0 ] , "middle" ) ;
926+ assert_eq ! ( event[ "span" ] [ "error.sources" ] [ 1 ] , "inner" ) ;
927+ }
928+ } )
929+ }
930+
830931 fn parse_as_json ( buffer : & MockMakeWriter ) -> serde_json:: Value {
831932 let buf = String :: from_utf8 ( buffer. buf ( ) . to_vec ( ) ) . unwrap ( ) ;
832933 let json = buf
0 commit comments