Bump version
**Breaking changes** - Remove `PartialEq<ReqComp> 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<ReqComps> for ReqComp` with `From<ReqComp> for ReqComps` - Modify `LogMiddleware::log` - Add tests - Run `cargo fmt`
This commit is contained in:
parent
d517d3d03c
commit
9e8d5ef5e9
|
@ -1,15 +1,13 @@
|
||||||
[package]
|
[package]
|
||||||
name = "tide_tracing"
|
name = "tide_tracing"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
authors = ["Michael Pfaff <michael@pfaff.dev>"]
|
authors = ["Michael Pfaff <michael@pfaff.dev>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nrid = { git = "https://git.pfaff.dev/michael/nrid.rs.git", tag = "v0.2.0", default-features = false }
|
nrid = { git = "https://git.pfaff.dev/michael/nrid.rs.git", tag = "v0.2.0", default-features = false }
|
||||||
tide = "0.16"
|
tide = "0.16"
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
num_enum = "0.5.1"
|
num_enum = "0.5"
|
||||||
|
|
99
src/lib.rs
99
src/lib.rs
|
@ -5,17 +5,13 @@
|
||||||
extern crate tracing;
|
extern crate tracing;
|
||||||
|
|
||||||
use nrid::Nrid;
|
use nrid::Nrid;
|
||||||
use std::time::Instant;
|
|
||||||
use tide::Middleware;
|
use tide::Middleware;
|
||||||
use tide::Next;
|
use tide::Next;
|
||||||
use tide::Request;
|
use tide::Request;
|
||||||
use tracing::Instrument;
|
use tracing::Instrument;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq)]
|
/// A traceable component of a [`Request`].
|
||||||
#[repr(transparent)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, num_enum::FromPrimitive)]
|
||||||
pub struct ReqComps(u8);
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, num_enum::FromPrimitive)]
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum ReqComp {
|
pub enum ReqComp {
|
||||||
#[num_enum(default)]
|
#[num_enum(default)]
|
||||||
|
@ -26,33 +22,40 @@ pub enum ReqComp {
|
||||||
Query = 0b00001000,
|
Query = 0b00001000,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A selection of traceable components of a [`Request`].
|
||||||
|
#[derive(Debug, Clone, Copy, Eq, Hash)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct ReqComps(u8);
|
||||||
|
|
||||||
impl ReqComps {
|
impl ReqComps {
|
||||||
pub const fn of(comp: ReqComp) -> Self {
|
#[inline]
|
||||||
Self(comp as u8)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn contains(self, mask: ReqComp) -> bool {
|
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
|
self & mask == mask
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl const Into<ReqComps> for ReqComp {
|
impl const Default for ReqComps {
|
||||||
fn into(self) -> ReqComps {
|
#[inline]
|
||||||
ReqComps::of(self)
|
fn default() -> Self {
|
||||||
|
Self(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl const core::cmp::PartialEq<ReqComp> for ReqComps {
|
// unfortunately, the automatic Into impl will not be const.
|
||||||
fn eq(&self, comp: &ReqComp) -> bool {
|
impl const From<ReqComp> for ReqComps {
|
||||||
self.0 & (*comp as u8) == *comp as u8
|
#[inline]
|
||||||
|
fn from(comp: ReqComp) -> Self {
|
||||||
|
Self(comp as u8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl const core::cmp::PartialEq for ReqComps {
|
impl const core::cmp::PartialEq for ReqComps {
|
||||||
|
#[inline]
|
||||||
fn eq(&self, comp: &Self) -> bool {
|
fn eq(&self, comp: &Self) -> bool {
|
||||||
self.0 == comp.0
|
self.0 == comp.0
|
||||||
}
|
}
|
||||||
|
@ -61,6 +64,7 @@ impl const core::cmp::PartialEq for ReqComps {
|
||||||
impl const core::ops::BitOr for ReqComp {
|
impl const core::ops::BitOr for ReqComp {
|
||||||
type Output = ReqComps;
|
type Output = ReqComps;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn bitor(self, rhs: Self) -> Self::Output {
|
fn bitor(self, rhs: Self) -> Self::Output {
|
||||||
ReqComps((self as u8) | (rhs as u8))
|
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 {
|
impl const core::ops::BitOr for ReqComps {
|
||||||
type Output = ReqComps;
|
type Output = ReqComps;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn bitor(self, rhs: Self) -> Self::Output {
|
fn bitor(self, rhs: Self) -> Self::Output {
|
||||||
ReqComps((self.0 as u8) | (rhs.0 as u8))
|
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<ReqComp> for ReqComps {
|
impl const core::ops::BitOr<ReqComp> for ReqComps {
|
||||||
type Output = ReqComps;
|
type Output = ReqComps;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn bitor(self, rhs: ReqComp) -> Self::Output {
|
fn bitor(self, rhs: ReqComp) -> Self::Output {
|
||||||
ReqComps((self.0 as u8) | (rhs as u8))
|
ReqComps((self.0 as u8) | (rhs as u8))
|
||||||
}
|
}
|
||||||
|
@ -84,6 +90,7 @@ impl const core::ops::BitOr<ReqComp> for ReqComps {
|
||||||
|
|
||||||
// TODO make `const` when is "stable" #57349 <https://github.com/rust-lang/rust/issues/57349>
|
// TODO make `const` when is "stable" #57349 <https://github.com/rust-lang/rust/issues/57349>
|
||||||
impl core::ops::BitOrAssign for ReqComps {
|
impl core::ops::BitOrAssign for ReqComps {
|
||||||
|
#[inline]
|
||||||
fn bitor_assign(&mut self, rhs: ReqComps) {
|
fn bitor_assign(&mut self, rhs: ReqComps) {
|
||||||
self.0 = (self.0 as u8) | (rhs.0 as u8)
|
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 <https://github.com/rust-lang/rust/issues/57349>
|
// TODO make `const` when is "stable" #57349 <https://github.com/rust-lang/rust/issues/57349>
|
||||||
impl core::ops::BitOrAssign<ReqComp> for ReqComps {
|
impl core::ops::BitOrAssign<ReqComp> for ReqComps {
|
||||||
|
#[inline]
|
||||||
fn bitor_assign(&mut self, rhs: ReqComp) {
|
fn bitor_assign(&mut self, rhs: ReqComp) {
|
||||||
self.0 = (self.0 as u8) | (rhs as u8)
|
self.0 = (self.0 as u8) | (rhs as u8)
|
||||||
}
|
}
|
||||||
|
@ -99,6 +107,7 @@ impl core::ops::BitOrAssign<ReqComp> for ReqComps {
|
||||||
impl const core::ops::BitAnd for ReqComp {
|
impl const core::ops::BitAnd for ReqComp {
|
||||||
type Output = ReqComps;
|
type Output = ReqComps;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn bitand(self, rhs: Self) -> Self::Output {
|
fn bitand(self, rhs: Self) -> Self::Output {
|
||||||
ReqComps((self as u8) & (rhs as u8))
|
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 {
|
impl const core::ops::BitAnd for ReqComps {
|
||||||
type Output = ReqComps;
|
type Output = ReqComps;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn bitand(self, rhs: Self) -> Self::Output {
|
fn bitand(self, rhs: Self) -> Self::Output {
|
||||||
ReqComps((self.0 as u8) & (rhs.0 as u8))
|
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<ReqComp> for ReqComps {
|
impl const core::ops::BitAnd<ReqComp> for ReqComps {
|
||||||
type Output = ReqComps;
|
type Output = ReqComps;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn bitand(self, rhs: ReqComp) -> Self::Output {
|
fn bitand(self, rhs: ReqComp) -> Self::Output {
|
||||||
ReqComps((self.0 as u8) & (rhs as u8))
|
ReqComps((self.0 as u8) & (rhs as u8))
|
||||||
}
|
}
|
||||||
|
@ -122,6 +133,7 @@ impl const core::ops::BitAnd<ReqComp> for ReqComps {
|
||||||
|
|
||||||
// TODO make `const` when is "stable" #57349 <https://github.com/rust-lang/rust/issues/57349>
|
// TODO make `const` when is "stable" #57349 <https://github.com/rust-lang/rust/issues/57349>
|
||||||
impl core::ops::BitAndAssign for ReqComps {
|
impl core::ops::BitAndAssign for ReqComps {
|
||||||
|
#[inline]
|
||||||
fn bitand_assign(&mut self, rhs: ReqComps) {
|
fn bitand_assign(&mut self, rhs: ReqComps) {
|
||||||
self.0 = (self.0 as u8) & (rhs.0 as u8)
|
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 <https://github.com/rust-lang/rust/issues/57349>
|
// TODO make `const` when is "stable" #57349 <https://github.com/rust-lang/rust/issues/57349>
|
||||||
impl core::ops::BitAndAssign<ReqComp> for ReqComps {
|
impl core::ops::BitAndAssign<ReqComp> for ReqComps {
|
||||||
|
#[inline]
|
||||||
fn bitand_assign(&mut self, rhs: ReqComp) {
|
fn bitand_assign(&mut self, rhs: ReqComp) {
|
||||||
self.0 = (self.0 as u8) & (rhs as u8)
|
self.0 = (self.0 as u8) & (rhs as u8)
|
||||||
}
|
}
|
||||||
|
@ -139,7 +152,8 @@ pub struct LogMiddleware {
|
||||||
pub components: ReqComps,
|
pub components: ReqComps,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LogMiddleware {
|
impl const Default for LogMiddleware {
|
||||||
|
#[inline]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
components: ReqComp::Method | ReqComp::Path,
|
components: ReqComp::Method | ReqComp::Path,
|
||||||
|
@ -154,31 +168,32 @@ impl LogMiddleware {
|
||||||
next: Next<'a, State>,
|
next: Next<'a, State>,
|
||||||
) -> tide::Result {
|
) -> tide::Result {
|
||||||
let id = Nrid::now();
|
let id = Nrid::now();
|
||||||
let span = debug_span!("Request", id = %id);
|
use tracing::field::Empty;
|
||||||
let comp = self.components;
|
let span = debug_span!("Request", id = %id, "http.method" = Empty, "http.path" = Empty, "conn.ip" = Empty, "http.query" = Empty);
|
||||||
let url = req.url();
|
let url = req.url();
|
||||||
if comp.contains(ReqComp::Method) {
|
if self.components.contains(ReqComp::Method) {
|
||||||
span.record("http.method", &tracing::field::display(req.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());
|
span.record("http.path", &url.path());
|
||||||
}
|
}
|
||||||
if comp.contains(ReqComp::IP) {
|
if self.components.contains(ReqComp::IP) {
|
||||||
span.record("conn.ip", &tracing::field::display(req.remote().unwrap_or("unknown").to_string()));
|
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(""));
|
span.record("http.query", &url.query().unwrap_or(""));
|
||||||
}
|
}
|
||||||
Ok(async {
|
async move {
|
||||||
let start = Instant::now();
|
|
||||||
let res = next.run(req).await;
|
let res = next.run(req).await;
|
||||||
let duration = start.elapsed();
|
|
||||||
let status = res.status();
|
let status = res.status();
|
||||||
debug_span!("Response", status = %status, duration = ?duration).in_scope(|| {});
|
debug!(status = %status, "Response");
|
||||||
res
|
Ok(res)
|
||||||
}
|
}
|
||||||
.instrument(span)
|
.instrument(span)
|
||||||
.await)
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,3 +203,23 @@ impl<State: Clone + Send + Sync + 'static> Middleware<State> for LogMiddleware {
|
||||||
self.log(req, next).await
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue