use std::borrow::Cow;
use backtrace::Backtrace;
use sentry_core::ClientOptions;
use crate::trim::is_well_known_not_in_app;
use crate::utils::{
demangle_symbol, filename, function_starts_with, parse_crate_name, strip_symbol,
};
use crate::{Frame, Stacktrace};
pub fn process_event_stacktrace(stacktrace: &mut Stacktrace, options: &ClientOptions) {
let mut any_in_app = false;
for frame in &mut stacktrace.frames {
let func_name = match frame.function {
Some(ref func) => func,
None => continue,
};
if frame.package.is_none() {
frame.package = parse_crate_name(func_name);
}
match frame.in_app {
Some(true) => {
any_in_app = true;
continue;
}
Some(false) => {
continue;
}
None => {}
}
for m in &options.in_app_include {
if function_starts_with(func_name, m) {
frame.in_app = Some(true);
any_in_app = true;
break;
}
}
if frame.in_app.is_some() {
continue;
}
for m in &options.in_app_exclude {
if function_starts_with(func_name, m) {
frame.in_app = Some(false);
break;
}
}
if frame.in_app.is_some() {
continue;
}
if is_well_known_not_in_app(func_name) {
frame.in_app = Some(false);
}
}
if !any_in_app {
for frame in &mut stacktrace.frames {
if frame.in_app.is_none() {
frame.in_app = Some(true);
}
}
}
}
pub fn backtrace_to_stacktrace(bt: &Backtrace) -> Option<Stacktrace> {
let frames = bt
.frames()
.iter()
.flat_map(|frame| {
let symbols = frame.symbols();
symbols
.iter()
.map(move |sym| {
let abs_path = sym.filename().map(|m| m.to_string_lossy().to_string());
let filename = abs_path.as_ref().map(|p| filename(p).to_string());
let real_symbol = sym
.name()
.map_or(Cow::Borrowed("<unknown>"), |n| Cow::Owned(n.to_string()));
let symbol = strip_symbol(&real_symbol);
let function = demangle_symbol(&symbol);
Frame {
symbol: if symbol != function {
Some(symbol.into())
} else {
None
},
function: Some(function),
instruction_addr: Some(frame.ip().into()),
abs_path,
filename,
lineno: sym.lineno().map(u64::from),
colno: None,
..Default::default()
}
})
.chain(if symbols.is_empty() {
Some(Frame {
instruction_addr: Some(frame.ip().into()),
function: Some("<unknown>".into()),
..Default::default()
})
} else {
None
})
})
.collect();
Stacktrace::from_frames_reversed(frames)
}