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 66 67 68 69 70 71 72 73 74 75 76 77 78
use std::time::Duration; use std::time::Instant; use tide::{Middleware, Next, Request, Response, Result}; pub struct LogMiddleware; impl LogMiddleware { fn log_request<State>(&self, request: &Request<State>) { log::info!( "<-- Request received, method: {}, path {}", request.method(), request.url().path() ); } fn log_response(&self, response: &Response, duration: Duration) { let status = response.status(); if response.status().is_server_error() { if let Some(error) = response.error() { log::error!("Internal error --> Response sent, message: {:?}, error_type: {}, status: {} - {}, duration: {:?}", error, error.type_name().unwrap_or("<unknown>"), status as u16, status.canonical_reason(), duration,); } else { log::error!( "Internal error --> Response sent, status: {} - {}, duration: {:?}", status as u16, status.canonical_reason(), duration, ); } } else if status.is_client_error() { if let Some(error) = response.error() { log::warn!("Client error --> Response sent, message: {:?}, error_type: {}, status: {} - {}, duration: {:?}", error, error.type_name().unwrap_or("<unknown>"), status as u16, status.canonical_reason(), duration,); } else { log::warn!( "Client error --> Response sent, status: {} - {}, duration: {:?}", status as u16, status.canonical_reason(), duration, ); } } else { log::info!( "--> Response sent, status: {} - {}, duration: {:?}", status as u16, status.canonical_reason(), duration, ); } } } #[async_trait::async_trait] impl<State: Clone + Send + Sync + 'static> Middleware<State> for LogMiddleware { async fn handle(&self, mut request: Request<State>, next: Next<'_, State>) -> crate::Result { if request.ext::<LogMiddleware>().is_some() { Ok(next.run(request).await) } else { request.set_ext(LogMiddleware); self.log_request(&request); let start = Instant::now(); let response = next.run(request).await; self.log_response(&response, start.elapsed()); Ok(response) } } }