From 9e8d5ef5e91c4e9a4610fd1269f1220b0e3cbb90 Mon Sep 17 00:00:00 2001 From: Michael Pfaff Date: Mon, 7 Mar 2022 16:24:50 -0500 Subject: [PATCH] Bump version **Breaking changes** - Remove `PartialEq for ReqComps` (use `ReqComps::contains` instead) - Rename `contains_many` to `contains_all` **Other changes** - Mark a bunch of methods `#[inline]` - Reorder structs - Add `Default for ReqComps` - Replace `Into for ReqComp` with `From for ReqComps` - Modify `LogMiddleware::log` - Add tests - Run `cargo fmt` --- Cargo.toml | 8 ++--- src/lib.rs | 99 ++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 70 insertions(+), 37 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f7cc941..2cbae64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,15 +1,13 @@ [package] name = "tide_tracing" -version = "0.5.0" +version = "0.6.0" authors = ["Michael Pfaff "] -edition = "2018" +edition = "2021" 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.2.0", default-features = false } tide = "0.16" tracing = "0.1" async-trait = "0.1" -num_enum = "0.5.1" +num_enum = "0.5" diff --git a/src/lib.rs b/src/lib.rs index 29e77ff..8886a75 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,17 +5,13 @@ extern crate tracing; use nrid::Nrid; -use std::time::Instant; use tide::Middleware; use tide::Next; use tide::Request; use tracing::Instrument; -#[derive(Clone, Copy, Debug, Eq)] -#[repr(transparent)] -pub struct ReqComps(u8); - -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, num_enum::FromPrimitive)] +/// A traceable component of a [`Request`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, num_enum::FromPrimitive)] #[repr(u8)] pub enum ReqComp { #[num_enum(default)] @@ -26,33 +22,40 @@ pub enum ReqComp { Query = 0b00001000, } +/// A selection of traceable components of a [`Request`]. +#[derive(Debug, Clone, Copy, Eq, Hash)] +#[repr(transparent)] +pub struct ReqComps(u8); + impl ReqComps { - pub const fn of(comp: ReqComp) -> Self { - Self(comp as u8) - } - + #[inline] pub const fn contains(self, mask: ReqComp) -> bool { - self & mask == mask + (self & mask).0 == mask as u8 } - pub const fn contains_many(self, mask: ReqComps) -> bool { + #[inline] + pub const fn contains_all(self, mask: ReqComps) -> bool { self & mask == mask } } -impl const Into for ReqComp { - fn into(self) -> ReqComps { - ReqComps::of(self) +impl const Default for ReqComps { + #[inline] + fn default() -> Self { + Self(0) } } -impl const core::cmp::PartialEq for ReqComps { - fn eq(&self, comp: &ReqComp) -> bool { - self.0 & (*comp as u8) == *comp as u8 +// unfortunately, the automatic Into impl will not be const. +impl const From for ReqComps { + #[inline] + fn from(comp: ReqComp) -> Self { + Self(comp as u8) } } impl const core::cmp::PartialEq for ReqComps { + #[inline] fn eq(&self, comp: &Self) -> bool { self.0 == comp.0 } @@ -61,6 +64,7 @@ impl const core::cmp::PartialEq for ReqComps { impl const core::ops::BitOr for ReqComp { type Output = ReqComps; + #[inline] fn bitor(self, rhs: Self) -> Self::Output { ReqComps((self as u8) | (rhs as u8)) } @@ -69,6 +73,7 @@ impl const core::ops::BitOr for ReqComp { impl const core::ops::BitOr for ReqComps { type Output = ReqComps; + #[inline] fn bitor(self, rhs: Self) -> Self::Output { ReqComps((self.0 as u8) | (rhs.0 as u8)) } @@ -77,6 +82,7 @@ impl const core::ops::BitOr for ReqComps { impl const core::ops::BitOr for ReqComps { type Output = ReqComps; + #[inline] fn bitor(self, rhs: ReqComp) -> Self::Output { ReqComps((self.0 as u8) | (rhs as u8)) } @@ -84,6 +90,7 @@ impl const core::ops::BitOr for ReqComps { // TODO make `const` when is "stable" #57349 impl core::ops::BitOrAssign for ReqComps { + #[inline] fn bitor_assign(&mut self, rhs: ReqComps) { self.0 = (self.0 as u8) | (rhs.0 as u8) } @@ -91,6 +98,7 @@ impl core::ops::BitOrAssign for ReqComps { // TODO make `const` when is "stable" #57349 impl core::ops::BitOrAssign for ReqComps { + #[inline] fn bitor_assign(&mut self, rhs: ReqComp) { self.0 = (self.0 as u8) | (rhs as u8) } @@ -99,6 +107,7 @@ impl core::ops::BitOrAssign for ReqComps { impl const core::ops::BitAnd for ReqComp { type Output = ReqComps; + #[inline] fn bitand(self, rhs: Self) -> Self::Output { ReqComps((self as u8) & (rhs as u8)) } @@ -107,6 +116,7 @@ impl const core::ops::BitAnd for ReqComp { impl const core::ops::BitAnd for ReqComps { type Output = ReqComps; + #[inline] fn bitand(self, rhs: Self) -> Self::Output { ReqComps((self.0 as u8) & (rhs.0 as u8)) } @@ -115,6 +125,7 @@ impl const core::ops::BitAnd for ReqComps { impl const core::ops::BitAnd for ReqComps { type Output = ReqComps; + #[inline] fn bitand(self, rhs: ReqComp) -> Self::Output { ReqComps((self.0 as u8) & (rhs as u8)) } @@ -122,6 +133,7 @@ impl const core::ops::BitAnd for ReqComps { // TODO make `const` when is "stable" #57349 impl core::ops::BitAndAssign for ReqComps { + #[inline] fn bitand_assign(&mut self, rhs: ReqComps) { self.0 = (self.0 as u8) & (rhs.0 as u8) } @@ -129,6 +141,7 @@ impl core::ops::BitAndAssign for ReqComps { // TODO make `const` when is "stable" #57349 impl core::ops::BitAndAssign for ReqComps { + #[inline] fn bitand_assign(&mut self, rhs: ReqComp) { self.0 = (self.0 as u8) & (rhs as u8) } @@ -139,7 +152,8 @@ pub struct LogMiddleware { pub components: ReqComps, } -impl Default for LogMiddleware { +impl const Default for LogMiddleware { + #[inline] fn default() -> Self { Self { components: ReqComp::Method | ReqComp::Path, @@ -154,31 +168,32 @@ impl LogMiddleware { next: Next<'a, State>, ) -> tide::Result { let id = Nrid::now(); - let span = debug_span!("Request", id = %id); - let comp = self.components; + use tracing::field::Empty; + let span = debug_span!("Request", id = %id, "http.method" = Empty, "http.path" = Empty, "conn.ip" = Empty, "http.query" = Empty); let url = req.url(); - if comp.contains(ReqComp::Method) { + if self.components.contains(ReqComp::Method) { span.record("http.method", &tracing::field::display(req.method())); } - if comp.contains(ReqComp::Path) { + if self.components.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 self.components.contains(ReqComp::IP) { + span.record( + "conn.ip", + &tracing::field::display(req.remote().unwrap_or("unknown").to_string()), + ); } - if comp.contains(ReqComp::Query) { + if self.components.contains(ReqComp::Query) { span.record("http.query", &url.query().unwrap_or("")); } - Ok(async { - let start = Instant::now(); + async move { let res = next.run(req).await; - let duration = start.elapsed(); let status = res.status(); - debug_span!("Response", status = %status, duration = ?duration).in_scope(|| {}); - res + debug!(status = %status, "Response"); + Ok(res) } .instrument(span) - .await) + .await } } @@ -188,3 +203,23 @@ impl Middleware for LogMiddleware { self.log(req, next).await } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_mask() { + const FIELDS: &'static [ReqComp] = &[ReqComp::Path, ReqComp::IP]; + + let mut comps = ReqComps::default(); + + for field in FIELDS { + comps |= *field; + } + + assert!(comps.contains(ReqComp::Path)); + assert!(comps.contains(ReqComp::IP)); + assert!(!comps.contains(ReqComp::Query)); + } +}