xitca_web/middleware/
logger.rs

1use tracing::{Level, warn};
2use xitca_http::util::middleware;
3
4use crate::service::Service;
5
6/// builder for tracing log middleware.
7///
8/// # Examples
9/// ```rust
10/// # use xitca_web::{handler::handler_service, middleware::Logger, route::get, App, WebContext};
11/// App::new()
12///     .at("/", get(handler_service(|| async { "hello,world!" })))
13///     # .at("/infer", handler_service(|_: &WebContext<'_>| async{ "infer type" }))
14///     // log http request and error with default setting.
15///     .enclosed(Logger::new());
16/// ```
17pub struct Logger {
18    logger: middleware::Logger,
19}
20
21impl Default for Logger {
22    fn default() -> Self {
23        Self::new()
24    }
25}
26
27impl Logger {
28    /// construct a new logger middleware builder with [`Level::INFO`] of verbosity it generate and captures.
29    /// would try to initialize global trace dispatcher.
30    pub fn new() -> Self {
31        Self::with_level(Level::INFO)
32    }
33
34    /// construct a new logger middleware builder with given [Level] of verbosity it generate and captures.
35    /// would try to initialize global trace dispatcher.
36    pub fn with_level(level: Level) -> Self {
37        if let Err(e) = tracing_subscriber::fmt().with_max_level(level).try_init() {
38            // the most likely case is trace dispatcher has already been set by user. log the warning and move on.
39            warn!("failed to initialize global trace dispatcher: {}", e);
40        }
41
42        Self {
43            logger: middleware::Logger::with_level(level),
44        }
45    }
46}
47
48impl<Arg> Service<Arg> for Logger
49where
50    middleware::Logger: Service<Arg>,
51{
52    type Response = <middleware::Logger as Service<Arg>>::Response;
53    type Error = <middleware::Logger as Service<Arg>>::Error;
54
55    async fn call(&self, arg: Arg) -> Result<Self::Response, Self::Error> {
56        self.logger.call(arg).await
57    }
58}