From 8a7353dc974dcc1a1fd5fcfe8b946b9cf09175b5 Mon Sep 17 00:00:00 2001 From: Michael Pfaff Date: Thu, 21 Jan 2021 11:49:00 -0500 Subject: [PATCH] Configurable, improved, middleware struct instead of function --- Cargo.lock | 4 +++- Cargo.toml | 8 ++++--- src/lib.rs | 66 ++++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 60 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a371974..98c6305 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1364,8 +1364,10 @@ dependencies = [ [[package]] name = "tide_tracing" -version = "0.1.0" +version = "0.2.0" dependencies = [ + "async-trait", + "chrono", "nrid", "tide", "tracing", diff --git a/Cargo.toml b/Cargo.toml index d8ba78a..cc89879 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tide_tracing" -version = "0.1.0" +version = "0.2.0" authors = ["Michael Pfaff "] edition = "2018" @@ -8,5 +8,7 @@ edition = "2018" [dependencies] nrid = { git = "https://git.pfaff.dev/michael/nrid.rs.git" } -tide = "0.15.0" -tracing = "0.1.15" +tide = { version = "0.15.0" } +tracing = { version = "0.1.15" } +async-trait = { version = "0.1.36" } +chrono = { version = "0.4.19" } diff --git a/src/lib.rs b/src/lib.rs index 37b78c5..5024ff2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,33 +1,71 @@ #[macro_use] extern crate tracing; -use core::future::Future; -use core::pin::Pin; +use chrono::Utc; use nrid::Nrid; -use std::time::Instant; +use tide::Middleware; use tide::Next; use tide::Request; use tracing::Instrument; use tracing::Level; -pub fn log_middleware<'a, State: 'static + Clone + Send + Sync>( - req: Request, - next: Next<'a, State>, -) -> Pin + Send + 'a>> { - Box::pin(async move { - let now = Instant::now(); +#[derive(Debug, Clone)] +pub struct LogMiddleware { + include_ip: bool, + include_query: bool, +} + +impl Default for LogMiddleware { + fn default() -> Self { + Self { + include_ip: false, + include_query: false, + } + } +} + +impl LogMiddleware { + async fn log<'a, State: Clone + Send + Sync + 'static>( + &'a self, + req: Request, + next: Next<'a, State>, + ) -> tide::Result { + let start = Utc::now(); let id = Nrid::now(); let uri = req.url().clone(); - // doesn't take forwarding into account and includes useless socket port information - // let ip = req.peer_addr().unwrap_or("unknown").to_string(); let ip = req.remote().unwrap_or("unknown").to_string(); let span = span!(Level::ERROR, "Request", id = %id); let res = async { - debug!(req.method = %req.method(), req.uri.path = uri.path(), req.uri.query = uri.query().unwrap_or(""), client_ip = %ip, received = ?now); + debug!(path = uri.path()); + + debug!(method = %req.method()); + + if self.include_query { + debug!(query = uri.query().unwrap_or("")); + } + + if self.include_ip { + debug!(client_ip = %ip); + } + + debug!(received = %start); + // debug!(method = %req.method(), query = uri.query().unwrap_or(""), client_ip = %ip, received = %start, "Request recieved"); let res = next.run(req).await; - debug!(status = %res.status(), elapsed = ?now.elapsed(), "Response"); + let end = Utc::now(); + let span = span!(Level::ERROR, "Response"); + async { + debug!(status = %res.status()); + debug!(duration = %end.signed_duration_since(start)); + }.instrument(span).await; res }.instrument(span).await; Ok(res) - }) + } +} + +#[async_trait::async_trait] +impl Middleware for LogMiddleware { + async fn handle(&self, req: Request, next: Next<'_, State>) -> tide::Result { + self.log(req, next).await + } }