From d517d3d03cbe5250869494301b441bc404130116 Mon Sep 17 00:00:00 2001 From: Michael Pfaff Date: Sun, 30 May 2021 03:00:41 -0400 Subject: [PATCH] Upgrade deps, remove unused deps, improve code --- Cargo.toml | 12 ++-- src/lib.rs | 204 +++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 158 insertions(+), 58 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 625797e..f7cc941 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tide_tracing" -version = "0.4.1" +version = "0.5.0" authors = ["Michael Pfaff "] edition = "2018" license = "MIT OR Apache-2.0" @@ -8,8 +8,8 @@ license = "MIT OR Apache-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nrid = { git = "https://git.pfaff.dev/michael/nrid.rs.git", tag = "v0.1.1" } -tide = { version = "0.16" } -tracing = { version = "0.1" } -async-trait = { version = "0.1" } -chrono = { version = "0.4" } +nrid = { git = "https://git.pfaff.dev/michael/nrid.rs.git", tag = "v0.2.0", default-features = false } +tide = "0.16" +tracing = "0.1" +async-trait = "0.1" +num_enum = "0.5.1" diff --git a/src/lib.rs b/src/lib.rs index fa19655..29e77ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,27 +1,148 @@ +#![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] + #[macro_use] extern crate tracing; -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; + +#[derive(Clone, Copy, Debug, Eq)] +#[repr(transparent)] +pub struct ReqComps(u8); + +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, num_enum::FromPrimitive)] +#[repr(u8)] +pub enum ReqComp { + #[num_enum(default)] + __Default = 0b00000000, + Method = 0b00000001, + Path = 0b00000010, + IP = 0b00000100, + Query = 0b00001000, +} + +impl ReqComps { + pub const fn of(comp: ReqComp) -> Self { + Self(comp as u8) + } + + pub const fn contains(self, mask: ReqComp) -> bool { + self & mask == mask + } + + pub const fn contains_many(self, mask: ReqComps) -> bool { + self & mask == mask + } +} + +impl const Into for ReqComp { + fn into(self) -> ReqComps { + ReqComps::of(self) + } +} + +impl const core::cmp::PartialEq for ReqComps { + fn eq(&self, comp: &ReqComp) -> bool { + self.0 & (*comp as u8) == *comp as u8 + } +} + +impl const core::cmp::PartialEq for ReqComps { + fn eq(&self, comp: &Self) -> bool { + self.0 == comp.0 + } +} + +impl const core::ops::BitOr for ReqComp { + type Output = ReqComps; + + fn bitor(self, rhs: Self) -> Self::Output { + ReqComps((self as u8) | (rhs as u8)) + } +} + +impl const core::ops::BitOr for ReqComps { + type Output = ReqComps; + + fn bitor(self, rhs: Self) -> Self::Output { + ReqComps((self.0 as u8) | (rhs.0 as u8)) + } +} + +impl const core::ops::BitOr for ReqComps { + type Output = ReqComps; + + fn bitor(self, rhs: ReqComp) -> Self::Output { + ReqComps((self.0 as u8) | (rhs as u8)) + } +} + +// TODO make `const` when is "stable" #57349 +impl core::ops::BitOrAssign for ReqComps { + fn bitor_assign(&mut self, rhs: ReqComps) { + self.0 = (self.0 as u8) | (rhs.0 as u8) + } +} + +// TODO make `const` when is "stable" #57349 +impl core::ops::BitOrAssign for ReqComps { + fn bitor_assign(&mut self, rhs: ReqComp) { + self.0 = (self.0 as u8) | (rhs as u8) + } +} + +impl const core::ops::BitAnd for ReqComp { + type Output = ReqComps; + + fn bitand(self, rhs: Self) -> Self::Output { + ReqComps((self as u8) & (rhs as u8)) + } +} + +impl const core::ops::BitAnd for ReqComps { + type Output = ReqComps; + + fn bitand(self, rhs: Self) -> Self::Output { + ReqComps((self.0 as u8) & (rhs.0 as u8)) + } +} + +impl const core::ops::BitAnd for ReqComps { + type Output = ReqComps; + + fn bitand(self, rhs: ReqComp) -> Self::Output { + ReqComps((self.0 as u8) & (rhs as u8)) + } +} + +// TODO make `const` when is "stable" #57349 +impl core::ops::BitAndAssign for ReqComps { + fn bitand_assign(&mut self, rhs: ReqComps) { + self.0 = (self.0 as u8) & (rhs.0 as u8) + } +} + +// TODO make `const` when is "stable" #57349 +impl core::ops::BitAndAssign for ReqComps { + fn bitand_assign(&mut self, rhs: ReqComp) { + self.0 = (self.0 as u8) & (rhs as u8) + } +} #[derive(Debug, Clone)] pub struct LogMiddleware { - pub include_ip: bool, - pub include_query: bool, - pub multiline: bool, + pub components: ReqComps, } impl Default for LogMiddleware { fn default() -> Self { Self { - include_ip: false, - include_query: false, - multiline: false, + components: ReqComp::Method | ReqComp::Path, } } } @@ -32,53 +153,32 @@ impl LogMiddleware { req: Request, next: Next<'a, State>, ) -> tide::Result { - let start = Utc::now(); let id = Nrid::now(); - let uri = req.url().clone(); - let ip = req.remote().unwrap_or("unknown").to_string(); - let span = span!(Level::ERROR, "Request", id = %id); - let res = async { - let path = uri.path(); - let method = req.method(); - let query = uri.query().unwrap_or(""); - let received = start.to_rfc3339_opts(chrono::SecondsFormat::AutoSi, false); - - if self.multiline { - debug!(path = path); - - debug!(method = %method); - - if self.include_ip { - debug!(client_ip = %ip); - } - - debug!(received = %received); - - if self.include_query { - debug!(query = query); - } - } else { - debug!(path = path, method = %method, client_ip = %ip, received = %received, query = query); - } - - // debug!(method = %req.method(), query = uri.query().unwrap_or(""), client_ip = %ip, received = %start, "Request recieved"); + let span = debug_span!("Request", id = %id); + let comp = self.components; + let url = req.url(); + if comp.contains(ReqComp::Method) { + span.record("http.method", &tracing::field::display(req.method())); + } + if comp.contains(ReqComp::Path) { + span.record("http.path", &url.path()); + } + if comp.contains(ReqComp::IP) { + span.record("conn.ip", &tracing::field::display(req.remote().unwrap_or("unknown").to_string())); + } + if comp.contains(ReqComp::Query) { + span.record("http.query", &url.query().unwrap_or("")); + } + Ok(async { + let start = Instant::now(); let res = next.run(req).await; - let end = Utc::now(); - let span = span!(Level::ERROR, "Response"); - async { - let status = res.status(); - let duration = end.signed_duration_since(start).to_std().unwrap(); - - if self.multiline { - debug!(status = %status); - debug!(duration = ?duration); - } else { - debug!(status = %status, duration = ?duration); - } - }.instrument(span).await; + let duration = start.elapsed(); + let status = res.status(); + debug_span!("Response", status = %status, duration = ?duration).in_scope(|| {}); res - }.instrument(span).await; - Ok(res) + } + .instrument(span) + .await) } }