1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use chrono::{DateTime, Utc};
use hyper::{Body, Request, Response};
use serde_json;

use crate::proxy::error::MiddlewareError;
use crate::proxy::middleware::MiddlewareResult::Next;
use crate::proxy::middleware::{Middleware, MiddlewareResult};
use crate::proxy::service::State;

#[derive(Clone, Default)]
pub struct Logger;

/// # Panics
/// May panic if the request state has not been initialized in `before_request`.
/// e.g If a middleware responded early before the logger in `before_request`.
impl Middleware for Logger {
    fn name() -> String {
        String::from("Logger")
    }

    fn before_request(
        &mut self,
        req: &mut Request<Body>,
        req_id: u64,
        state: &State,
    ) -> Result<MiddlewareResult, MiddlewareError> {
        info!(
            "[{}] Starting a {} request to {}",
            &req_id.to_string()[..6],
            req.method(),
            req.uri()
        );
        let now = serde_json::to_string(&Utc::now()).expect("[Logger] Cannot serialize DateTime");
        self.set_state(req_id, state, now)?;
        Ok(Next)
    }

    fn after_request(
        &mut self,
        _res: Option<&mut Response<Body>>,
        req_id: u64,
        state: &State,
    ) -> Result<MiddlewareResult, MiddlewareError> {
        let start_time = self.get_state(req_id, state)?;
        match start_time {
            Some(time) => {
                let start_time: DateTime<Utc> = serde_json::from_str(&time)?;

                info!(
                    "[{}] Request took {}ms",
                    &req_id.to_string()[..6],
                    (Utc::now() - start_time).num_milliseconds()
                );
            }
            None => error!("[Logger] start time not found in state"),
        }
        Ok(Next)
    }
}

impl Logger {
    pub fn new() -> Self {
        Logger {}
    }
}