1use std::{future::Future, pin::Pin, time::Instant};
2
3use viz_core::{http, Context, Middleware, Response, Result};
4use viz_utils::tracing;
5
6#[derive(Debug, Default)]
8pub struct Logger {}
9
10impl Logger {
11 async fn run(&self, cx: &mut Context) -> Result<Response> {
12 let start = Instant::now();
13 let method = cx.method().to_string();
14 let path = cx.uri().path().to_owned();
15
16 tracing::trace!("> {:>7} {}", method, path);
17
18 match cx.next().await {
19 Ok(res) => {
20 let status = res.status();
21
22 if status == http::StatusCode::INTERNAL_SERVER_ERROR {
23 tracing::error!(
24 "< {:>7} {} {} {:?}",
25 method,
26 path,
27 status.as_u16(),
28 start.elapsed(),
29 );
30 } else {
31 tracing::trace!(
32 "< {:>7} {} {} {:?}",
33 method,
34 path,
35 status.as_u16(),
36 start.elapsed(),
37 );
38 }
39
40 Ok(res)
41 }
42 Err(err) => {
43 tracing::error!("< {:>7} {} {} {:?}", method, path, err, start.elapsed(),);
44 Err(err)
45 }
46 }
47 }
48}
49
50impl<'a> Middleware<'a, Context> for Logger {
51 type Output = Result<Response>;
52
53 #[must_use]
54 fn call(
55 &'a self,
56 cx: &'a mut Context,
57 ) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>> {
58 Box::pin(self.run(cx))
59 }
60}