mc-ingress/src/opaque_error.rs

132 lines
3.4 KiB
Rust

use std::{
error::Error,
fmt::{self, Debug},
};
use tracing::Level;
use tracing_error::SpanTrace;
#[derive(Debug)]
pub struct OpaqueError {
span_trace: SpanTrace,
pub context: String,
pub level: Level,
kind: Option<String>,
}
impl fmt::Display for OpaqueError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// optional: only print span trace if requested "{:#}"
if f.alternate() {
let mut vec = Vec::new();
self.span_trace.with_spans(|metadata, _fields| {
vec.push(metadata.name());
true
});
if vec.len() > 1 {
write!(f, "trace = {}", vec.pop().unwrap())?;
}
vec.reverse();
for s in vec {
write!(f, "::{}", s)?;
}
};
write!(f, " {}", self.context)?;
Ok(())
}
}
impl Error for OpaqueError {}
impl OpaqueError {
pub fn create(context: &str) -> OpaqueError {
Self {
span_trace: SpanTrace::capture(),
context: context.to_string(),
level: Level::ERROR,
kind: None,
}
}
pub fn create_with_kind(context: &str, kind: &str) -> OpaqueError {
Self {
span_trace: SpanTrace::capture(),
context: context.to_string(),
level: Level::ERROR,
kind: Some(kind.to_string()),
}
}
pub fn print_span_trace(&self) -> FancyTrace {
let mut vec: Vec<(&str, String)> = Vec::new();
self.span_trace.with_spans(|metadata, _fields| {
vec.push((metadata.name(), _fields.into()));
true
});
let str = vec.iter().rfold(String::new(), |mut acc, x| {
let first = acc.len() == 0;
if !first {
// TODO: should this code be hardcoded?
acc.push_str("\x1b[2m:\x1b[0m");
}
acc.push_str(x.0);
if !x.1.is_empty() {
acc.push_str("{");
acc.push_str(&x.1);
acc.push_str("}");
}
acc
});
FancyTrace { str }
}
pub fn set_level(mut self, lvl: Level) -> Self {
self.level = lvl;
self
}
pub fn get_kind(&self) -> &str {
match self.kind.as_ref() {
Some(x) => &x,
None => &self.context,
}
}
}
pub struct FancyTrace {
str: String,
}
impl fmt::Display for FancyTrace {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "\x1b[2m{{{{\x1b[0m {} \x1b[2m}}}}\x1b[0m", self.str)
}
}
impl From<String> for OpaqueError {
fn from(value: String) -> Self {
Self {
span_trace: SpanTrace::capture(),
context: value,
level: Level::ERROR,
kind: None,
}
}
}
impl From<&str> for OpaqueError {
fn from(value: &str) -> Self {
Self {
span_trace: SpanTrace::capture(),
context: value.to_string(),
level: Level::ERROR,
kind: None,
}
}
}
impl From<crate::packets::ParseErrorTrace> for OpaqueError {
fn from(value: crate::packets::ParseErrorTrace) -> Self {
Self {
span_trace: value.context,
context: format!("{:?}", value.inner),
level: Level::ERROR,
kind: None,
}
}
}