ckb_sentry_backtrace/
integration.rs

1use std::thread;
2
3use sentry_core::protocol::{Event, Thread};
4use sentry_core::{ClientOptions, Integration};
5
6use crate::current_stacktrace;
7use crate::process::process_event_stacktrace;
8
9/// Integration to process Event stacktraces.
10///
11/// This integration will trim backtraces, depending on the `trim_backtraces`
12/// and `extra_border_frames` options.
13/// It will then classify each frame according to the `in_app_include` and
14/// `in_app_exclude` options.
15#[derive(Debug, Default)]
16pub struct ProcessStacktraceIntegration;
17
18impl ProcessStacktraceIntegration {
19    /// Creates a new Integration to process stacktraces.
20    pub fn new() -> Self {
21        Self::default()
22    }
23}
24
25impl Integration for ProcessStacktraceIntegration {
26    fn name(&self) -> &'static str {
27        "process-stacktrace"
28    }
29
30    fn process_event(
31        &self,
32        mut event: Event<'static>,
33        options: &ClientOptions,
34    ) -> Option<Event<'static>> {
35        for exc in &mut event.exception {
36            if let Some(ref mut stacktrace) = exc.stacktrace {
37                process_event_stacktrace(stacktrace, &options);
38            }
39        }
40        Some(event)
41    }
42}
43
44/// Integration to attach stacktraces to Events.
45///
46/// This integration will add an additional thread backtrace to captured
47/// messages, respecting the `attach_stacktrace` option.
48#[derive(Debug, Default)]
49pub struct AttachStacktraceIntegration;
50
51impl AttachStacktraceIntegration {
52    /// Creates a new Integration to attach stacktraces to Events.
53    pub fn new() -> Self {
54        Self::default()
55    }
56}
57
58impl Integration for AttachStacktraceIntegration {
59    fn name(&self) -> &'static str {
60        "attach-stacktrace"
61    }
62
63    fn process_event(
64        &self,
65        mut event: Event<'static>,
66        options: &ClientOptions,
67    ) -> Option<Event<'static>> {
68        if options.attach_stacktrace && event.exception.is_empty() {
69            let thread = current_thread(true);
70            if thread.stacktrace.is_some() {
71                event.threads.values.push(thread);
72            }
73        }
74        Some(event)
75    }
76}
77
78/// Captures information about the current thread.
79///
80/// If `with_stack` is set to `true` the current stacktrace is
81/// attached.
82pub fn current_thread(with_stack: bool) -> Thread {
83    // NOTE: `as_u64` is nightly only
84    // See https://github.com/rust-lang/rust/issues/67939
85    let thread_id: u64 = unsafe { std::mem::transmute(thread::current().id()) };
86    Thread {
87        id: Some(thread_id.to_string().into()),
88        name: thread::current().name().map(str::to_owned),
89        current: true,
90        stacktrace: if with_stack {
91            current_stacktrace()
92        } else {
93            None
94        },
95        ..Default::default()
96    }
97}