xitca_http/util/middleware/
logger.rs1use tracing::Level;
2use xitca_service::Service;
3
4#[derive(Clone)]
6pub struct Logger {
7 level: Level,
8}
9
10impl Default for Logger {
11 fn default() -> Self {
12 Self::new()
13 }
14}
15
16impl Logger {
17 pub fn new() -> Self {
19 Self::with_level(Level::WARN)
20 }
21
22 pub fn with_level(level: Level) -> Self {
24 Self { level }
25 }
26}
27
28impl<S, E> Service<Result<S, E>> for Logger {
29 type Response = service::LoggerService<S>;
30 type Error = E;
31
32 async fn call(&self, res: Result<S, E>) -> Result<Self::Response, Self::Error> {
33 res.map(|service| service::LoggerService {
34 service,
35 level: self.level,
36 })
37 }
38}
39
40mod service {
41 use std::error;
42
43 use tracing::{Instrument, event, span};
44 use xitca_service::ready::ReadyService;
45
46 use crate::http::{BorrowReq, Method, Uri, header::HeaderMap};
47
48 use super::*;
49
50 pub struct LoggerService<S> {
51 pub(super) service: S,
52 pub(super) level: Level,
53 }
54
55 impl<S, Req> Service<Req> for LoggerService<S>
56 where
57 S: Service<Req>,
58 Req: BorrowReq<Method> + BorrowReq<Uri> + BorrowReq<HeaderMap>,
59 S::Error: error::Error,
60 {
61 type Response = S::Response;
62 type Error = S::Error;
63
64 #[inline]
65 async fn call(&self, req: Req) -> Result<Self::Response, Self::Error> {
66 let method: &Method = req.borrow();
67 let uri: &Uri = req.borrow();
68
69 macro_rules! span2 {
70 ($lvl:expr, $name:expr, $($fields:tt)*) => {
71 match $lvl {
72 Level::TRACE => span!(Level::TRACE, $name, $($fields)*),
73 Level::DEBUG => span!(Level::DEBUG, $name, $($fields)*),
74 Level::INFO => span!(Level::INFO, $name, $($fields)*),
75 Level::WARN => span!(Level::WARN, $name, $($fields)*),
76 Level::ERROR => span!(Level::ERROR, $name, $($fields)*),
77 }
78 }
79 }
80
81 let span = span2!(
82 self.level,
83 "request",
84 method = %method,
85 uri = %uri
86 );
87
88 async {
89 event!(target: "on_request", Level::INFO, "serving request");
90 match self.service.call(req).await {
91 Ok(res) => {
92 event!(target: "on_response", Level::INFO, "sending response");
93 Ok(res)
94 }
95 Err(e) => {
96 event!(target: "on_error", Level::WARN, "{}", e);
97 Err(e)
98 }
99 }
100 }
101 .instrument(span)
102 .await
103 }
104 }
105
106 impl<S> ReadyService for LoggerService<S>
107 where
108 S: ReadyService,
109 {
110 type Ready = S::Ready;
111
112 #[inline]
113 async fn ready(&self) -> Self::Ready {
114 self.service.ready().await
115 }
116 }
117}