1#![doc(html_favicon_url = "https://sentry-brand.storage.googleapis.com/favicon.ico")]
28#![doc(html_logo_url = "https://sentry-brand.storage.googleapis.com/sentry-glyph-black.png")]
29#![warn(missing_docs)]
30#![deny(unsafe_code)]
31#![warn(missing_doc_code_examples)]
32#![allow(deprecated)]
33
34use std::panic::PanicInfo;
35
36use failure::{Error, Fail};
37use sentry_backtrace::parse_stacktrace;
38use sentry_core::parse_type_from_debug;
39use sentry_core::protocol::{Event, Exception, Level};
40use sentry_core::types::Uuid;
41use sentry_core::{ClientOptions, Hub, Integration};
42
43#[derive(Debug, Default)]
45#[deprecated = "The `failure` integration is deprecated and will be removed in the future."]
46pub struct FailureIntegration;
47
48impl FailureIntegration {
49    pub fn new() -> Self {
51        Self::default()
52    }
53}
54
55impl Integration for FailureIntegration {
56    fn name(&self) -> &'static str {
57        "failure"
58    }
59
60    fn setup(&self, cfg: &mut ClientOptions) {
61        cfg.in_app_exclude.push("failure::");
62        cfg.extra_border_frames.extend_from_slice(&[
63            "failure::error_message::err_msg",
64            "failure::backtrace::Backtrace::new",
65            "failure::backtrace::internal::InternalBacktrace::new",
66            "failure::Fail::context",
67        ]);
68    }
69}
70
71#[deprecated = "The `failure` integration is deprecated and will be removed in the future."]
84pub fn panic_extractor(info: &PanicInfo<'_>) -> Option<Event<'static>> {
85    let error = info.payload().downcast_ref::<Error>()?;
86    Some(Event {
87        level: Level::Fatal,
88        ..event_from_error(error)
89    })
90}
91
92#[deprecated = "The `failure` integration is deprecated and will be removed in the future."]
100pub fn exception_from_single_fail<F: Fail + ?Sized>(
101    f: &F,
102    bt: Option<&failure::Backtrace>,
103) -> Exception {
104    let dbg = format!("{:?}", f);
105    Exception {
106        ty: parse_type_from_debug(&dbg).to_owned(),
107        value: Some(f.to_string()),
108        stacktrace: bt
109            .map(|bt| format!("{:#?}", bt))
111            .and_then(|x| parse_stacktrace(&x)),
112        ..Default::default()
113    }
114}
115
116#[deprecated = "The `failure` integration is deprecated and will be removed in the future."]
118pub fn event_from_error(err: &failure::Error) -> Event<'static> {
119    let mut exceptions: Vec<_> = err
120        .iter_chain()
121        .enumerate()
122        .map(|(idx, cause)| {
123            let bt = match cause.backtrace() {
124                Some(bt) => Some(bt),
125                None if idx == 0 => Some(err.backtrace()),
126                None => None,
127            };
128            exception_from_single_fail(cause, bt)
129        })
130        .collect();
131    exceptions.reverse();
132
133    Event {
134        exception: exceptions.into(),
135        level: Level::Error,
136        ..Default::default()
137    }
138}
139
140#[deprecated = "The `failure` integration is deprecated and will be removed in the future."]
142pub fn event_from_fail<F: Fail + ?Sized>(fail: &F) -> Event<'static> {
143    let mut exceptions = vec![exception_from_single_fail(fail, fail.backtrace())];
144
145    let mut ptr: Option<&dyn Fail> = None;
146    while let Some(cause) = ptr.map(Fail::cause).unwrap_or_else(|| fail.cause()) {
147        exceptions.push(exception_from_single_fail(cause, cause.backtrace()));
148        ptr = Some(cause);
149    }
150
151    exceptions.reverse();
152    Event {
153        exception: exceptions.into(),
154        level: Level::Error,
155        ..Default::default()
156    }
157}
158
159#[deprecated = "The `failure` integration is deprecated and will be removed in the future."]
163pub fn capture_error(err: &Error) -> Uuid {
164    Hub::with_active(|hub| FailureHubExt::capture_error(hub.as_ref(), err))
165}
166
167#[deprecated = "The `failure` integration is deprecated and will be removed in the future."]
171pub fn capture_fail<F: Fail + ?Sized>(fail: &F) -> Uuid {
172    Hub::with_active(|hub| hub.capture_fail(fail))
173}
174
175#[deprecated = "The `failure` integration is deprecated and will be removed in the future."]
177pub trait FailureHubExt {
178    fn capture_error(&self, err: &Error) -> Uuid;
180    fn capture_fail<F: Fail + ?Sized>(&self, fail: &F) -> Uuid;
182}
183
184impl FailureHubExt for Hub {
185    fn capture_error(&self, err: &Error) -> Uuid {
186        self.capture_event(event_from_error(err))
187    }
188
189    fn capture_fail<F: Fail + ?Sized>(&self, fail: &F) -> Uuid {
190        self.capture_event(event_from_fail(fail))
191    }
192}
193
194#[deprecated = "The `failure` integration is deprecated and will be removed in the future."]
197pub trait FailureResultExt {
198    type Value;
200    fn fallible_unwrap(self) -> Self::Value;
203}
204
205impl<T, E> FailureResultExt for Result<T, E>
206where
207    E: Into<Error>,
208{
209    type Value = T;
210    fn fallible_unwrap(self) -> Self::Value {
211        match self {
212            Ok(v) => v,
213            Err(e) => {
214                let e: Error = e.into();
215                panic!(e)
216            }
217        }
218    }
219}