1use std::backtrace::{Backtrace, BacktraceStatus};
2use std::fmt;
3use tracing_error::SpanTrace;
4use yansi::Paint;
5
6#[derive(Debug)]
10pub struct ErrorTrace {
11 spantrace: SpanTrace,
12 backtrace: Backtrace,
13}
14
15impl ErrorTrace {
16 pub fn capture() -> Self {
17 Self {
18 spantrace: SpanTrace::capture(),
19 backtrace: Backtrace::force_capture(),
20 }
21 }
22
23 fn write_trace(f: &mut fmt::Formatter<'_>, kind: &str, trace: &dyn fmt::Display) -> fmt::Result {
24 writeln!(f, "{}\n{trace}", format_args!("{kind}:").red().bold())
25 }
26}
27
28impl fmt::Display for ErrorTrace {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 let backtrace = &self.backtrace;
31
32 match backtrace.status() {
33 BacktraceStatus::Captured => Self::write_trace(f, "Backtrace", backtrace)?,
34 BacktraceStatus::Disabled => writeln!(
37 f,
38 "{}",
39 "⚠️ Backtrace wasn't captured. This is probably a bug in our error \
40 trace capturing code."
41 .red(),
42 )?,
43 BacktraceStatus::Unsupported => writeln!(f, "{}", "backtrace is unsupported".red())?,
44 _ => writeln!(f, "{}\n{backtrace}", "Backtrace is in unknown status:".red())?,
45 };
46
47 let spantrace = &self.spantrace;
48
49 match spantrace.status() {
50 tracing_error::SpanTraceStatus::CAPTURED => {
51 write!(f, "{}\n{spantrace}", "Spantrace:".red().bold())?;
52 },
53 tracing_error::SpanTraceStatus::EMPTY => {
54 write!(
55 f,
56 "{}. It may be expected if the error happened outside of \
57 any spans, or those spans were not enabled. You may try \
58 capturing it by enabling {} logging or increasing its level \
59 via MARKER_LOG env variable in cargo-marker. Spantrace capturing \
60 in marker_rustc_driver isn't supported yet.",
61 "⚠️ Spantrace wasn't captured".yellow(),
62 "tracing".bold()
63 )?;
64 },
65 tracing_error::SpanTraceStatus::UNSUPPORTED => f.write_str("spantrace is unsupported")?,
66 }
67
68 Ok(())
69 }
70}