@@ -17,21 +17,30 @@ pub fn client_options() -> sentry::ClientOptions {
1717///
1818/// `std::error::Error` doesn't support backtraces, thus `sentry::event_from_error`
1919/// doesn't either. This function works against `ReportableError` instead to
20- /// access its backtrace.
21- pub fn event_from_error < E > ( err : & E ) -> sentry:: protocol:: Event < ' static >
22- where
23- E : ReportableError + ' static ,
24- {
25- let mut exceptions = vec ! [ exception_from_error_with_backtrace( err) ] ;
20+ /// extract backtraces from it and its chain of `reportable_source's.
21+ ///
22+ /// A caveat of this function is that it cannot extract
23+ /// `ReportableError`s/backtraces that occur in a chain after a
24+ /// `std::error::Error` occurs: as `std::error::Error::source` only allows
25+ /// downcasting to a concrete type, not `dyn ReportableError`.
26+ pub fn event_from_error (
27+ mut reportable_err : & dyn ReportableError ,
28+ ) -> sentry:: protocol:: Event < ' static > {
29+ let mut exceptions = vec ! [ ] ;
2630
27- let mut source = err . source ( ) ;
28- while let Some ( err ) = source {
29- let exception = if let Some ( err ) = err . downcast_ref :: < E > ( ) {
30- exception_from_error_with_backtrace ( err )
31- } else {
32- exception_from_error ( err )
31+ // Gather reportable_source()'s for their backtraces
32+ loop {
33+ exceptions . push ( exception_from_reportable_error ( reportable_err ) ) ;
34+ reportable_err = match reportable_err . reportable_source ( ) {
35+ Some ( reportable_err ) => reportable_err ,
36+ None => break ,
3337 } ;
34- exceptions. push ( exception) ;
38+ }
39+
40+ // Then fallback to source() for remaining Errors
41+ let mut source = reportable_err. source ( ) ;
42+ while let Some ( err) = source {
43+ exceptions. push ( exception_from_error ( err) ) ;
3544 source = err. source ( ) ;
3645 }
3746
4554
4655/// Custom `exception_from_error` support function for `ReportableError`
4756///
48- /// Based moreso on sentry_failure's `exception_from_single_fail`.
49- fn exception_from_error_with_backtrace ( err : & dyn ReportableError ) -> sentry:: protocol:: Exception {
57+ /// Based moreso on sentry_failure's `exception_from_single_fail`. Includes a
58+ /// stacktrace if available.
59+ fn exception_from_reportable_error ( err : & dyn ReportableError ) -> sentry:: protocol:: Exception {
5060 let mut exception = exception_from_error ( err) ;
5161 if let Some ( backtrace) = err. backtrace ( ) {
5262 exception. stacktrace = sentry_backtrace:: backtrace_to_stacktrace ( backtrace)
0 commit comments