sentry_backtrace/
process.rs
1use std::borrow::Cow;
2
3use backtrace::Backtrace;
4use sentry_core::ClientOptions;
5
6use crate::trim::{is_well_known_not_in_app, trim_stacktrace};
7use crate::utils::{
8 demangle_symbol, filename, function_starts_with, parse_crate_name, strip_symbol,
9};
10use crate::{Frame, Stacktrace};
11
12pub fn process_event_stacktrace(stacktrace: &mut Stacktrace, options: &ClientOptions) {
17 if options.trim_backtraces {
19 trim_stacktrace(stacktrace, |frame, _| {
20 if let Some(ref func) = frame.function {
21 options.extra_border_frames.contains(&func.as_str())
22 } else {
23 false
24 }
25 })
26 }
27
28 let mut any_in_app = false;
30 for frame in &mut stacktrace.frames {
31 let func_name = match frame.function {
32 Some(ref func) => func,
33 None => continue,
34 };
35
36 if frame.package.is_none() {
38 frame.package = parse_crate_name(func_name);
39 }
40
41 match frame.in_app {
42 Some(true) => {
43 any_in_app = true;
44 continue;
45 }
46 Some(false) => {
47 continue;
48 }
49 None => {}
50 }
51
52 for m in &options.in_app_include {
53 if function_starts_with(func_name, m) {
54 frame.in_app = Some(true);
55 any_in_app = true;
56 break;
57 }
58 }
59
60 if frame.in_app.is_some() {
61 continue;
62 }
63
64 for m in &options.in_app_exclude {
65 if function_starts_with(func_name, m) {
66 frame.in_app = Some(false);
67 break;
68 }
69 }
70
71 if frame.in_app.is_some() {
72 continue;
73 }
74
75 if is_well_known_not_in_app(func_name) {
76 frame.in_app = Some(false);
77 }
78 }
79
80 if !any_in_app {
81 for frame in &mut stacktrace.frames {
82 if frame.in_app.is_none() {
83 frame.in_app = Some(true);
84 }
85 }
86 }
87}
88
89pub fn backtrace_to_stacktrace(bt: &Backtrace) -> Option<Stacktrace> {
91 let frames = bt
92 .frames()
93 .iter()
94 .flat_map(|frame| {
95 let symbols = frame.symbols();
98 symbols
99 .iter()
100 .map(move |sym| {
101 let abs_path = sym.filename().map(|m| m.to_string_lossy().to_string());
102 let filename = abs_path.as_ref().map(|p| filename(p).to_string());
103 let real_symbol = sym
104 .name()
105 .map_or(Cow::Borrowed("<unknown>"), |n| Cow::Owned(n.to_string()));
106 let symbol = strip_symbol(&real_symbol);
107 let function = demangle_symbol(&symbol);
108 Frame {
109 symbol: if symbol != function {
110 Some(symbol.into())
111 } else {
112 None
113 },
114 function: Some(function),
115 instruction_addr: Some(frame.ip().into()),
116 abs_path,
117 filename,
118 lineno: sym.lineno().map(u64::from),
119 colno: None,
120 ..Default::default()
121 }
122
123 })
126 .chain(if symbols.is_empty() {
127 Some(Frame {
128 instruction_addr: Some(frame.ip().into()),
129 function: Some("<unknown>".into()),
130 ..Default::default()
131 })
132 } else {
133 None
134 })
135 })
136 .collect();
137 Stacktrace::from_frames_reversed(frames)
138}