azure_functions/
backtrace.rs

1use backtrace::BacktraceFrame;
2use std::env;
3use std::fmt;
4
5pub struct Backtrace {
6    inner: backtrace::Backtrace,
7}
8
9impl Backtrace {
10    pub fn new() -> Backtrace {
11        if !Backtrace::is_enabled() {
12            return Backtrace {
13                inner: Vec::<BacktraceFrame>::new().into(),
14            };
15        }
16
17        let mut found_start = false;
18        let mut found_end = false;
19
20        // This attempts to filter to only the frames relevant to the Azure Function
21        let frames: Vec<BacktraceFrame> = backtrace::Backtrace::new()
22            .frames()
23            .iter()
24            .filter_map(|frame| {
25                if found_end {
26                    return None;
27                }
28
29                for symbol in frame.symbols() {
30                    if let Some(name) = symbol.name() {
31                        let name = format!("{}", name);
32
33                        // Check for the start (i.e. where the panic starts)
34                        if !found_start {
35                            if name.starts_with("std::panicking::begin_panic::")
36                                || name.starts_with("core::panicking::panic::")
37                            {
38                                found_start = true;
39                            }
40                            return None;
41                        }
42
43                        // Check for the end (the invoker frame)
44                        if !found_end && name.contains("::__invoke_") {
45                            found_end = true;
46                            return None;
47                        }
48                    }
49                }
50
51                Some(frame.clone())
52            })
53            .collect();
54
55        Backtrace {
56            inner: frames.into(),
57        }
58    }
59
60    pub fn is_enabled() -> bool {
61        env::var("RUST_BACKTRACE").unwrap_or_else(|_| "0".to_owned()) == "1"
62    }
63}
64
65impl fmt::Display for Backtrace {
66    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67        use std::fmt::Debug;
68
69        if !Backtrace::is_enabled() {
70            return write!(
71                f,
72                "\nNote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace."
73            );
74        }
75
76        if self.inner.frames().is_empty() {
77            return Ok(());
78        }
79
80        writeln!(f)?;
81        self.inner.fmt(f)
82    }
83}