use crate::{Context, Layer, Service};
use rama_utils::macros::define_inner_service_accessors;
use std::fmt;
pub struct TraceErr<S> {
inner: S,
level: tracing::Level,
}
impl<S> fmt::Debug for TraceErr<S>
where
S: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TraceErr")
.field("inner", &self.inner)
.field("level", &self.level)
.finish()
}
}
impl<S> Clone for TraceErr<S>
where
S: Clone,
{
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
level: self.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 {
TraceErr { inner, level }
}
define_inner_service_accessors!();
}
impl<S, State, Request> Service<State, Request> for TraceErr<S>
where
Request: Send + 'static,
S: Service<State, Request, Error: std::fmt::Display + Send + Sync + 'static>,
State: Clone + Send + Sync + 'static,
{
type Response = S::Response;
type Error = S::Error;
#[inline]
async fn serve(
&self,
ctx: Context<State>,
req: Request,
) -> Result<Self::Response, Self::Error> {
let level = self.level;
let res = self.inner.serve(ctx, req).await;
if let Err(ref err) = res {
match level {
tracing::Level::TRACE => tracing::trace!(error = %err, "rama service failed"),
tracing::Level::DEBUG => tracing::debug!(error = %err, "rama service failed"),
tracing::Level::INFO => tracing::info!(error = %err, "rama service failed"),
tracing::Level::WARN => tracing::warn!(error = %err, "rama service failed"),
tracing::Level::ERROR => tracing::error!(error = %err, "rama service failed"),
}
}
res
}
}
impl TraceErrLayer {
pub const fn new() -> Self {
Self::with_level(tracing::Level::ERROR)
}
pub const fn with_level(level: tracing::Level) -> Self {
TraceErrLayer { 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)
}
}