diff --git a/ecstore/src/chunk_stream.rs b/ecstore/src/chunk_stream.rs index 43a4dbce5..96930ef38 100644 --- a/ecstore/src/chunk_stream.rs +++ b/ecstore/src/chunk_stream.rs @@ -1,7 +1,7 @@ +use crate::error::StdError; use bytes::Bytes; use futures::pin_mut; use futures::stream::{Stream, StreamExt}; -use s3s::StdError; use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; diff --git a/ecstore/src/erasure.rs b/ecstore/src/erasure.rs index f1a3c97d0..f32822938 100644 --- a/ecstore/src/erasure.rs +++ b/ecstore/src/erasure.rs @@ -1,3 +1,4 @@ +use crate::error::StdError; use anyhow::anyhow; use anyhow::Error; use anyhow::Result; @@ -6,7 +7,6 @@ use futures::future::join_all; use futures::{Stream, StreamExt}; use reed_solomon_erasure::galois_8::ReedSolomon; use s3s::dto::StreamingBlob; -use s3s::StdError; use tokio::io::AsyncWrite; use tokio::io::AsyncWriteExt; use tokio::io::DuplexStream; diff --git a/ecstore/src/error.rs b/ecstore/src/error.rs index f18a27b2f..92489bfd9 100644 --- a/ecstore/src/error.rs +++ b/ecstore/src/error.rs @@ -1,79 +1,68 @@ -use s3s::S3Error; -use s3s::S3ErrorCode; -use s3s::StdError; -use std::fmt::Display; -use std::panic::Location; +use tracing_error::{SpanTrace, SpanTraceStatus}; -use tracing::error; - -#[derive(Debug)] -pub struct Error { - source: StdError, -} +pub type StdError = Box; pub type Result = std::result::Result; +#[derive(Debug)] +pub struct Error { + inner: Box, + span_trace: SpanTrace, +} + impl Error { + /// Create a new error from a `std::error::Error`. #[must_use] #[track_caller] pub fn new(source: StdError) -> Self { - log(&*source); - Self { source } + Self { + inner: source, + span_trace: SpanTrace::capture(), + } } + /// Create a new error from a string. #[must_use] #[track_caller] pub fn from_string(s: impl Into) -> Self { Self::new(s.into().into()) } -} -impl From for Error -where - E: std::error::Error + Send + Sync + 'static, -{ - #[track_caller] - fn from(source: E) -> Self { - Self::new(Box::new(source)) + /// Returns `true` if the inner type is the same as `T`. + #[inline] + pub fn is(&self) -> bool { + self.inner.is::() + } + + /// Returns some reference to the inner value if it is of type `T`, or + /// `None` if it isn't. + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + self.inner.downcast_ref() + } + + /// Returns some mutable reference to the inner value if it is of type `T`, or + /// `None` if it isn't. + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + self.inner.downcast_mut() } } -impl From for S3Error { - fn from(e: Error) -> Self { - S3Error::with_source(S3ErrorCode::InternalError, e.source) +impl From for Error { + fn from(e: T) -> Self { + Self::new(e.into()) } } -impl Display for Error { +impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.source.fmt(f) - } -} + write!(f, "{}", self.inner)?; -#[inline] -#[track_caller] -pub(crate) fn log(source: &dyn std::error::Error) { - if cfg!(feature = "binary") { - let location = Location::caller(); - let span_trace = tracing_error::SpanTrace::capture(); - - error!( - target: "s3s_fs_internal_error", - %location, - error=%source, - "span trace:\n{span_trace}" - ); - } -} - -macro_rules! try_ { - ($result:expr) => { - match $result { - Ok(val) => val, - Err(err) => { - $crate::error::log(&err); - return Err(::s3s::S3Error::internal_error(err)); - } + if self.span_trace.status() != SpanTraceStatus::EMPTY { + write!(f, "\nspan_trace:\n{}", self.span_trace)?; } - }; + + Ok(()) + } }