use std::{
backtrace::{Backtrace, BacktraceStatus},
error::Error,
fmt,
};
use tracing_error::{SpanTrace, SpanTraceStatus};
#[derive(Debug)]
pub struct Failure<E> {
error: E,
backtrace: Backtrace,
span_trace: Option<String>,
}
impl<E> Failure<E> {
pub fn capture(error: E) -> Self {
Self::with_backtrace(error, Backtrace::capture())
}
pub fn with_backtrace(error: E, backtrace: Backtrace) -> Self {
let trace = SpanTrace::capture();
let span_trace = (trace.status() == SpanTraceStatus::CAPTURED).then(|| trace.to_string());
Self {
error,
backtrace,
span_trace,
}
}
pub fn error(&self) -> &E {
&self.error
}
pub fn backtrace(&self) -> &Backtrace {
&self.backtrace
}
pub fn span_trace(&self) -> Option<&str> {
self.span_trace.as_deref()
}
pub fn into_inner(self) -> E {
self.error
}
}
impl<E> Failure<E> {
pub fn captured_backtrace(&self) -> Option<&Backtrace> {
(self.backtrace.status() == BacktraceStatus::Captured).then_some(&self.backtrace)
}
}
impl<E: fmt::Display> fmt::Display for Failure<E> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
self.error.fmt(formatter)
}
}
impl<E: Error + 'static> Error for Failure<E> {
fn source(&self) -> Option<&(dyn Error + 'static)> {
self.error.source()
}
}