rama_core/layer/
trace_err.rs

1use crate::{Context, Layer, Service};
2use rama_utils::macros::define_inner_service_accessors;
3use std::fmt;
4
5/// Service which traces the error using [`tracing`],
6/// of the inner [`Service`].
7pub struct TraceErr<S> {
8    inner: S,
9    level: tracing::Level,
10}
11
12impl<S> fmt::Debug for TraceErr<S>
13where
14    S: fmt::Debug,
15{
16    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17        f.debug_struct("TraceErr")
18            .field("inner", &self.inner)
19            .field("level", &self.level)
20            .finish()
21    }
22}
23
24impl<S> Clone for TraceErr<S>
25where
26    S: Clone,
27{
28    fn clone(&self) -> Self {
29        Self {
30            inner: self.inner.clone(),
31            level: self.level,
32        }
33    }
34}
35
36/// A [`Layer`] that produces [`TraceErr`] services.
37///
38/// [`Layer`]: crate::Layer
39#[derive(Clone, Debug)]
40pub struct TraceErrLayer {
41    level: tracing::Level,
42}
43
44impl<S> TraceErr<S> {
45    /// Creates a new [`TraceErr`] service.
46    pub const fn new(inner: S) -> Self {
47        Self::with_level(inner, tracing::Level::ERROR)
48    }
49
50    /// Crates a new [`TraceErr`] service with the given [`tracing::Level`].
51    pub const fn with_level(inner: S, level: tracing::Level) -> Self {
52        TraceErr { inner, level }
53    }
54
55    define_inner_service_accessors!();
56}
57
58impl<S, State, Request> Service<State, Request> for TraceErr<S>
59where
60    Request: Send + 'static,
61    S: Service<State, Request, Error: std::fmt::Display + Send + Sync + 'static>,
62    State: Clone + Send + Sync + 'static,
63{
64    type Response = S::Response;
65    type Error = S::Error;
66
67    #[inline]
68    async fn serve(
69        &self,
70        ctx: Context<State>,
71        req: Request,
72    ) -> Result<Self::Response, Self::Error> {
73        let level = self.level;
74        let res = self.inner.serve(ctx, req).await;
75        if let Err(ref err) = res {
76            match level {
77                tracing::Level::TRACE => tracing::trace!(error = %err, "rama service failed"),
78                tracing::Level::DEBUG => tracing::debug!(error = %err, "rama service failed"),
79                tracing::Level::INFO => tracing::info!(error = %err, "rama service failed"),
80                tracing::Level::WARN => tracing::warn!(error = %err, "rama service failed"),
81                tracing::Level::ERROR => tracing::error!(error = %err, "rama service failed"),
82            }
83        }
84        res
85    }
86}
87
88impl TraceErrLayer {
89    /// Creates a new [`TraceErrLayer`].
90    pub const fn new() -> Self {
91        Self::with_level(tracing::Level::ERROR)
92    }
93
94    /// Creates a new [`TraceErrLayer`] with the given [`tracing::Level`].
95    pub const fn with_level(level: tracing::Level) -> Self {
96        TraceErrLayer { level }
97    }
98}
99
100impl Default for TraceErrLayer {
101    fn default() -> Self {
102        Self::new()
103    }
104}
105
106impl<S> Layer<S> for TraceErrLayer {
107    type Service = TraceErr<S>;
108
109    fn layer(&self, inner: S) -> Self::Service {
110        TraceErr::with_level(inner, self.level)
111    }
112}