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}