@@ -4,6 +4,28 @@ use crate::metadata::ReportMetadata;
44
55use super :: Reporter ;
66
7+ use std:: fmt;
8+
9+ #[ derive( Debug , thiserror:: Error ) ]
10+ pub struct MultiError {
11+ errors : Vec < ( String , Box < dyn std:: error:: Error + Send > ) > ,
12+ }
13+
14+ impl fmt:: Display for MultiError {
15+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
16+ write ! ( f, "{{" ) ?;
17+ let mut first = true ;
18+ for ( reporter, err) in self . errors . iter ( ) {
19+ if !first {
20+ write ! ( f, ", " ) ?;
21+ }
22+ first = false ;
23+ write ! ( f, "{}: {}" , reporter, err) ?;
24+ }
25+ write ! ( f, "}}" )
26+ }
27+ }
28+
729#[ derive( Debug ) ]
830/// A reporter that reports profiling results to several destinations.
931///
@@ -26,14 +48,21 @@ impl Reporter for MultiReporter {
2648 jfr : Vec < u8 > ,
2749 metadata : & ReportMetadata ,
2850 ) -> Result < ( ) , Box < dyn std:: error:: Error + Send > > {
29- let errs = futures:: future:: join_all (
30- self . reporters
31- . iter ( )
32- . map ( |reporter| reporter. report ( jfr. clone ( ) , metadata) ) ,
33- )
51+ let jfr_ref = & jfr[ ..] ;
52+ let errors = futures:: future:: join_all ( self . reporters . iter ( ) . map ( |reporter| async move {
53+ reporter
54+ . report ( jfr_ref. to_owned ( ) , metadata)
55+ . await
56+ . map_err ( move |e| ( format ! ( "{:?}" , reporter) , e) )
57+ } ) )
3458 . await ;
35- // return the first error
36- errs. into_iter ( ) . collect ( )
59+ // return all errors
60+ let errors: Vec < _ > = errors. into_iter ( ) . flat_map ( |e| e. err ( ) ) . collect ( ) ;
61+ if errors. is_empty ( ) {
62+ Ok ( ( ) )
63+ } else {
64+ Err ( Box :: new ( MultiError { errors } ) )
65+ }
3766 }
3867}
3968
@@ -73,20 +102,20 @@ pub mod test {
73102
74103 #[ derive( Debug , thiserror:: Error ) ]
75104 enum Error {
76- #[ error( "failed" ) ]
77- Failed ,
105+ #[ error( "failed: {0} " ) ]
106+ Failed ( String ) ,
78107 }
79108
80109 #[ derive( Debug ) ]
81- struct ErrReporter ;
110+ struct ErrReporter ( String ) ;
82111 #[ async_trait]
83112 impl Reporter for ErrReporter {
84113 async fn report (
85114 & self ,
86115 _jfr : Vec < u8 > ,
87116 _metadata : & ReportMetadata ,
88117 ) -> Result < ( ) , Box < dyn std:: error:: Error + Send > > {
89- Err ( Box :: new ( Error :: Failed ) )
118+ Err ( Box :: new ( Error :: Failed ( self . 0 . clone ( ) ) ) )
90119 }
91120 }
92121
@@ -119,11 +148,19 @@ pub mod test {
119148 let signal_after = Arc :: new ( AtomicBool :: new ( false ) ) ;
120149 let reporter = MultiReporter :: new ( vec ! [
121150 Box :: new( OkReporter ( signal_before. clone( ) ) ) as Box <dyn Reporter + Send + Sync >,
122- Box :: new( ErrReporter ) as Box <dyn Reporter + Send + Sync >,
151+ Box :: new( ErrReporter ( "foo" . to_owned( ) ) ) as Box <dyn Reporter + Send + Sync >,
152+ Box :: new( ErrReporter ( "bar" . to_owned( ) ) ) as Box <dyn Reporter + Send + Sync >,
123153 Box :: new( OkReporter ( signal_after. clone( ) ) ) as Box <dyn Reporter + Send + Sync >,
124154 ] ) ;
125155 // test that reports are done and return an error
126- reporter. report ( vec ! [ ] , & DUMMY_METADATA ) . await . unwrap_err ( ) ;
156+ let err = format ! (
157+ "{}" ,
158+ reporter. report( vec![ ] , & DUMMY_METADATA ) . await . unwrap_err( )
159+ ) ;
160+ assert_eq ! (
161+ err,
162+ "{ErrReporter(\" foo\" ): failed: foo, ErrReporter(\" bar\" ): failed: bar}"
163+ ) ;
127164 // test that reports are done even though a reporter errored
128165 assert ! ( signal_before. load( atomic:: Ordering :: Relaxed ) ) ;
129166 assert ! ( signal_after. load( atomic:: Ordering :: Relaxed ) ) ;
0 commit comments