use crate::{Layer, Service};
use rama_utils::macros::define_inner_service_accessors;
#[derive(Debug, Clone)]
pub struct TraceErr<S> {
inner: S,
level: tracing::Level,
}
#[derive(Clone, Debug)]
pub struct TraceErrLayer {
level: tracing::Level,
}
impl<S> TraceErr<S> {
pub const fn new(inner: S) -> Self {
Self::with_level(inner, tracing::Level::ERROR)
}
pub const fn with_level(inner: S, level: tracing::Level) -> Self {
Self { inner, level }
}
define_inner_service_accessors!();
}
impl<S, Input> Service<Input> for TraceErr<S>
where
Input: Send + 'static,
S: Service<Input, Error: core::fmt::Display + Send + Sync + 'static>,
{
type Output = S::Output;
type Error = S::Error;
#[inline]
async fn serve(&self, input: Input) -> Result<Self::Output, Self::Error> {
let level = self.level;
let res = self.inner.serve(input).await;
if let Err(ref err) = res {
match level {
tracing::Level::TRACE => tracing::trace!("rama service failed: {err}"),
tracing::Level::DEBUG => tracing::debug!("rama service failed: {err}"),
tracing::Level::INFO => tracing::info!("rama service failed: {err}"),
tracing::Level::WARN => tracing::warn!("rama service failed: {err}"),
tracing::Level::ERROR => tracing::error!("rama service failed: {err}"),
}
}
res
}
}
impl TraceErrLayer {
#[must_use]
pub const fn new() -> Self {
Self::with_level(tracing::Level::ERROR)
}
#[must_use]
pub const fn with_level(level: tracing::Level) -> Self {
Self { level }
}
}
impl Default for TraceErrLayer {
fn default() -> Self {
Self::new()
}
}
impl<S> Layer<S> for TraceErrLayer {
type Service = TraceErr<S>;
fn layer(&self, inner: S) -> Self::Service {
TraceErr::with_level(inner, self.level)
}
}