diff --git a/core/src/ctxt.rs b/core/src/ctxt.rs index 6c01dbf..9bba491 100644 --- a/core/src/ctxt.rs +++ b/core/src/ctxt.rs @@ -154,9 +154,13 @@ impl Ctxt for Empty { } mod internal { - use core::{marker::PhantomData, ops::ControlFlow}; + use core::marker::PhantomData; - use crate::{key::Key, props::Props, value::Value}; + use crate::{ + key::Key, + props::{ControlFlow, Props}, + value::Value, + }; pub struct Slot(*const T, PhantomData<*mut fn()>); @@ -171,7 +175,10 @@ mod internal { } impl Props for Slot { - fn for_each<'a, F: FnMut(Key<'a>, Value<'a>) -> ControlFlow<()>>(&'a self, for_each: F) { + fn for_each<'a, F: FnMut(Key<'a>, Value<'a>) -> ControlFlow>( + &'a self, + for_each: F, + ) -> ControlFlow { self.get().for_each(for_each) } } @@ -187,14 +194,11 @@ mod alloc_support { use super::*; mod internal { - use core::{marker::PhantomData, mem, ops::ControlFlow}; + use core::{marker::PhantomData, mem}; use crate::{ - event::Event, key::Key, - props::{ErasedProps, Props}, - template::Template, - time::Timestamp, + props::{ControlFlow, ErasedProps, Props}, value::Value, }; @@ -233,10 +237,10 @@ mod alloc_support { } impl Props for ErasedCurrentProps { - fn for_each<'a, F: FnMut(Key<'a>, Value<'a>) -> ControlFlow<()>>( + fn for_each<'a, F: FnMut(Key<'a>, Value<'a>) -> ControlFlow>( &'a self, for_each: F, - ) { + ) -> ControlFlow { self.get().for_each(for_each) } } diff --git a/core/src/event.rs b/core/src/event.rs index d063864..1e18793 100644 --- a/core/src/event.rs +++ b/core/src/event.rs @@ -1,21 +1,17 @@ -use core::{ - fmt, - ops::{ControlFlow, Range}, -}; +use core::fmt; use crate::{ - extent::Extent, + extent::{Extent, ToExtent}, key::{Key, ToKey}, - props::{ByRef, Chain, ErasedProps, Props}, + props::{ByRef, Chain, ControlFlow, ErasedProps, Props}, template::{Render, Template}, - time::Timestamp, value::{ToValue, Value}, - well_known::{MSG_KEY, TPL_KEY, TSS_KEY, TS_KEY}, + well_known::{MSG_KEY, TPL_KEY}, }; #[derive(Clone)] pub struct Event<'a, P> { - extent: Option>, + extent: Extent, tpl: Template<'a>, props: P, } @@ -35,16 +31,16 @@ impl<'a, P: Props> fmt::Debug for Event<'a, P> { } impl<'a, P> Event<'a, P> { - pub fn new(extent: impl Extent, tpl: Template<'a>, props: P) -> Self { + pub fn new(extent: impl ToExtent, tpl: Template<'a>, props: P) -> Self { Event { - extent: extent.extent(), + extent: extent.to_extent(), tpl, props, } } - pub fn extent(&self) -> Option<&Range> { - self.extent.as_ref() + pub fn extent(&self) -> &Extent { + &self.extent } } @@ -65,30 +61,8 @@ impl<'a, P: Props> Event<'a, P> { } } - pub fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>>( - &'kv self, - mut for_each: F, - ) { - let mut reserved = || { - if let Some(ref ts) = self.extent { - if ts.start != ts.end { - for_each(TSS_KEY.to_key(), ts.start.to_value())?; - } - - for_each(TS_KEY.to_key(), ts.end.to_value())?; - } - - for_each(TPL_KEY.to_key(), self.tpl.to_value())?; - for_each(MSG_KEY.to_key(), Msg::new_ref(self).to_value())?; - - ControlFlow::Continue(()) - }; - - if let ControlFlow::Break(()) = reserved() { - return; - } - - self.props.for_each(for_each); + pub fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>(&'kv self, for_each: F) { + let _ = Props::for_each(self, for_each); } pub fn props(&self) -> &P { @@ -112,9 +86,23 @@ impl<'a, P: Props> Event<'a, P> { } } +impl<'a, P> ToExtent for Event<'a, P> { + fn to_extent(&self) -> Extent { + self.extent.clone() + } +} + impl<'a, P: Props> Props for Event<'a, P> { - fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>>(&'kv self, for_each: F) { - self.for_each(for_each) + fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>( + &'kv self, + mut for_each: F, + ) -> ControlFlow { + self.extent.for_each(&mut for_each)?; + + for_each(TPL_KEY.to_key(), self.tpl.to_value())?; + for_each(MSG_KEY.to_key(), Msg::new_ref(self).to_value())?; + + self.props.for_each(for_each) } } diff --git a/core/src/extent.rs b/core/src/extent.rs index 1c1a4ee..4761400 100644 --- a/core/src/extent.rs +++ b/core/src/extent.rs @@ -1,52 +1,97 @@ use crate::{ empty::Empty, - event::Event, + key::{Key, ToKey}, + props::{ControlFlow, Props}, time::{Clock, Timer, Timestamp}, + value::{ToValue, Value}, + well_known::{TIMESTAMP_KEY, TIMESTAMP_START_KEY}, }; use core::ops::Range; -pub trait Extent { - fn extent(&self) -> Option>; +#[derive(Debug, Clone)] +pub struct Extent(Option>); + +impl Extent { + pub fn point(ts: Timestamp) -> Self { + Extent(Some(ts..ts)) + } + + pub fn span(ts: Range) -> Self { + Extent(Some(ts)) + } + + pub fn empty() -> Self { + Extent(None) + } + + pub fn to_point(&self) -> Option<&Timestamp> { + self.0.as_ref().map(|ts| &ts.end) + } + + pub fn to_span(&self) -> Option<&Range> { + self.0.as_ref().filter(|ts| ts.start != ts.end) + } + + pub fn is_empty(&self) -> bool { + self.0.is_none() + } } -impl<'a, T: Extent + ?Sized> Extent for &'a T { - fn extent(&self) -> Option> { - (**self).extent() +impl Props for Extent { + fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>( + &'kv self, + mut for_each: F, + ) -> ControlFlow { + if let Some(ref ts) = self.0 { + if ts.start != ts.end { + for_each(TIMESTAMP_START_KEY.to_key(), ts.start.to_value())?; + } + + for_each(TIMESTAMP_KEY.to_key(), ts.end.to_value()) + } else { + ControlFlow::Continue(()) + } } } -impl Extent for Empty { - fn extent(&self) -> Option> { - None +pub trait ToExtent { + fn to_extent(&self) -> Extent; +} + +impl<'a, T: ToExtent + ?Sized> ToExtent for &'a T { + fn to_extent(&self) -> Extent { + (**self).to_extent() } } -impl<'a, P> Extent for Event<'a, P> { - fn extent(&self) -> Option> { - self.extent().cloned() +impl ToExtent for Empty { + fn to_extent(&self) -> Extent { + Extent::empty() } } -impl Extent for Timestamp { - fn extent(&self) -> Option> { - Some(*self..*self) +impl ToExtent for Option { + fn to_extent(&self) -> Extent { + self.as_ref() + .map(|ts| ts.to_extent()) + .unwrap_or_else(Extent::empty) } } -impl Extent for Range { - fn extent(&self) -> Option> { - Some(self.clone()) +impl ToExtent for Timestamp { + fn to_extent(&self) -> Extent { + Extent::point(*self) } } -impl Extent for Timer { - fn extent(&self) -> Option> { - self.extent() +impl ToExtent for Range { + fn to_extent(&self) -> Extent { + Extent::span(self.clone()) } } -impl Extent for Option { - fn extent(&self) -> Option> { - self.as_ref().and_then(|ts| ts.extent()) +impl ToExtent for Timer { + fn to_extent(&self) -> Extent { + self.extent() } } diff --git a/core/src/props.rs b/core/src/props.rs index b9a9cb7..82f2c82 100644 --- a/core/src/props.rs +++ b/core/src/props.rs @@ -1,4 +1,4 @@ -use core::{borrow::Borrow, ops::ControlFlow}; +use core::borrow::Borrow; use crate::{ empty::Empty, @@ -6,8 +6,14 @@ use crate::{ value::{ToValue, Value}, }; +pub type ControlFlow = core::ops::ControlFlow<()>; +pub use core::ops::ControlFlow::*; + pub trait Props { - fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>>(&'kv self, for_each: F); + fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>( + &'kv self, + for_each: F, + ) -> ControlFlow; fn get<'v, K: ToKey>(&'v self, key: K) -> Option> { let key = key.to_key(); @@ -17,9 +23,9 @@ pub trait Props { if k == key { value = Some(v); - ControlFlow::Break(()) + Break(()) } else { - ControlFlow::Continue(()) + Continue(()) } }); @@ -49,7 +55,10 @@ pub trait Props { } impl<'a, P: Props + ?Sized> Props for &'a P { - fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>>(&'kv self, for_each: F) { + fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>( + &'kv self, + for_each: F, + ) -> ControlFlow { (**self).for_each(for_each) } @@ -59,55 +68,57 @@ impl<'a, P: Props + ?Sized> Props for &'a P { } impl Props for Option

{ - fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>>(&'kv self, for_each: F) { + fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>( + &'kv self, + for_each: F, + ) -> ControlFlow { match self { Some(props) => props.for_each(for_each), - None => (), + None => Continue(()), } } } #[cfg(feature = "alloc")] impl<'a, P: Props + ?Sized + 'a> Props for alloc::boxed::Box

{ - fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>>(&'kv self, for_each: F) { + fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>( + &'kv self, + for_each: F, + ) -> ControlFlow { (**self).for_each(for_each) } } impl Props for (K, V) { - fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>>( - &'kv self, - mut for_each: F, - ) { + fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>(&'kv self, mut for_each: F) { for_each(self.0.to_key(), self.1.to_value()); } } +// TODO: Make this based on `Props` impl Props for [(K, V)] { - fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>>( + fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>( &'kv self, mut for_each: F, - ) { + ) -> ControlFlow { for (k, v) in self { - match for_each(k.to_key(), v.to_value()) { - ControlFlow::Continue(()) => continue, - ControlFlow::Break(()) => return, - } + for_each(k.to_key(), v.to_value())?; } + + Continue(()) } } impl Props for [Option<(K, V)>] { - fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>>( + fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>( &'kv self, mut for_each: F, - ) { + ) -> ControlFlow { for (k, v) in self.iter().filter_map(|kv| kv.as_ref()) { - match for_each(k.to_key(), v.to_value()) { - ControlFlow::Continue(()) => continue, - ControlFlow::Break(()) => return, - } + for_each(k.to_key(), v.to_value())?; } + + Continue(()) } } @@ -115,13 +126,16 @@ impl Props for [T; N] where [T]: Props, { - fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>>(&'kv self, for_each: F) { + fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>( + &'kv self, + for_each: F, + ) -> ControlFlow { (self as &[_]).for_each(for_each) } } impl Props for Empty { - fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>>(&'kv self, _: F) {} + fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>(&'kv self, _: F) {} } pub struct Chain { @@ -130,24 +144,11 @@ pub struct Chain { } impl Props for Chain { - fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>>( + fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>( &'kv self, mut for_each: F, - ) { - let mut cf = ControlFlow::Continue(()); - - self.first.for_each(|k, v| match for_each(k, v) { - ControlFlow::Continue(()) => ControlFlow::Continue(()), - ControlFlow::Break(r) => { - cf = ControlFlow::Break(()); - ControlFlow::Break(r) - } - }); - - if let ControlFlow::Break(()) = cf { - return; - } - + ) -> ControlFlow { + self.first.for_each(&mut for_each)?; self.second.for_each(for_each) } @@ -161,7 +162,10 @@ impl Props for Chain { pub struct ByRef<'a, T: ?Sized>(&'a T); impl<'a, P: Props + ?Sized> Props for ByRef<'a, P> { - fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>>(&'kv self, for_each: F) { + fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>( + &'kv self, + for_each: F, + ) -> ControlFlow { self.0.for_each(for_each) } } @@ -172,15 +176,15 @@ pub struct Filter { } impl bool> Props for Filter { - fn for_each<'kv, FE: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>>( + fn for_each<'kv, FE: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>( &'kv self, mut for_each: FE, - ) { + ) -> ControlFlow { self.src.for_each(|k, v| { if (self.filter)(k.by_ref(), v.by_ref()) { for_each(k, v) } else { - ControlFlow::Continue(()) + Continue(()) } }) } @@ -196,15 +200,15 @@ impl bool> Props for Filter { } mod internal { - use core::ops::ControlFlow; + use super::ControlFlow; use crate::{key::Key, value::Value}; pub trait DispatchProps { fn dispatch_for_each<'kv, 'f>( &'kv self, - for_each: &'f mut dyn FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>, - ); + for_each: &'f mut dyn FnMut(Key<'kv>, Value<'kv>) -> ControlFlow, + ) -> ControlFlow; fn dispatch_get(&self, key: Key) -> Option; } @@ -227,8 +231,8 @@ impl internal::SealedProps for P { impl internal::DispatchProps for P { fn dispatch_for_each<'kv, 'f>( &'kv self, - for_each: &'f mut dyn FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>, - ) { + for_each: &'f mut dyn FnMut(Key<'kv>, Value<'kv>) -> ControlFlow, + ) -> ControlFlow { self.for_each(for_each) } @@ -238,10 +242,10 @@ impl internal::DispatchProps for P { } impl<'a> Props for dyn ErasedProps + 'a { - fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow<()>>( + fn for_each<'kv, F: FnMut(Key<'kv>, Value<'kv>) -> ControlFlow>( &'kv self, mut for_each: F, - ) { + ) -> ControlFlow { self.erase_props().0.dispatch_for_each(&mut for_each) } diff --git a/core/src/time.rs b/core/src/time.rs index 8e64a4e..452f58d 100644 --- a/core/src/time.rs +++ b/core/src/time.rs @@ -1,13 +1,8 @@ -use core::{ - cmp, fmt, - ops::{Range, Sub}, - str, - str::FromStr, - time::Duration, -}; +use core::{cmp, fmt, ops::Sub, str, str::FromStr, time::Duration}; use crate::{ empty::Empty, + extent::Extent, value::{ToValue, Value}, }; @@ -166,18 +161,14 @@ impl Timer { } } - pub fn extent(&self) -> Option> { + pub fn extent(&self) -> Extent { let end = self.clock.now(); match (self.start, end) { - (Some(start), Some(end)) => Some(start..end), - _ => None, + (Some(start), Some(end)) => Extent::span(start..end), + _ => Extent::empty(), } } - - pub fn elapsed(&self) -> Option { - self.extent().map(|ex| ex.end - ex.start) - } } #[derive(Debug)] diff --git a/core/src/well_known.rs b/core/src/well_known.rs index 5144431..5a9d888 100644 --- a/core/src/well_known.rs +++ b/core/src/well_known.rs @@ -6,16 +6,17 @@ use crate::{ value::Value, }; -pub const TS_KEY: &'static str = "#ts"; -pub const TSS_KEY: &'static str = "#tss"; +pub const TIMESTAMP_KEY: &'static str = "#ts"; +pub const TIMESTAMP_START_KEY: &'static str = "#tss"; pub const MSG_KEY: &'static str = "#msg"; pub const TPL_KEY: &'static str = "#tpl"; pub const ERR_KEY: &'static str = "err"; pub const LVL_KEY: &'static str = "lvl"; -pub const SPAN_ID_KEY: &'static str = "span_id"; -pub const SPAN_PARENT_KEY: &'static str = "span_parent"; -pub const TRACE_ID_KEY: &'static str = "trace_id"; +pub const MODULE_KEY: &'static str = "mod"; +pub const TRACE_ID_KEY: &'static str = "tr"; +pub const SPAN_ID_KEY: &'static str = "sp"; +pub const SPAN_PARENT_KEY: &'static str = "spp"; pub const fn is_reserved(key: &str) -> bool { let key = key.as_bytes(); @@ -30,18 +31,22 @@ pub const fn is_reserved(key: &str) -> bool { } pub trait WellKnown: Props { - fn ts(&self) -> Option { - self.get(TS_KEY)?.to_timestamp() + fn timestamp(&self) -> Option { + self.get(TIMESTAMP_KEY)?.to_timestamp() } - fn tss(&self) -> Option { - self.get(TSS_KEY)?.to_timestamp() + fn timestamp_start(&self) -> Option { + self.get(TIMESTAMP_START_KEY)?.to_timestamp() } fn lvl(&self) -> Option { self.get(LVL_KEY)?.to_level() } + fn module(&self) -> Option { + self.get(MODULE_KEY) + } + fn trace_id(&self) -> Option { self.get(TRACE_ID_KEY)?.to_trace_id() } diff --git a/targets/otlp/src/logs.rs b/targets/otlp/src/logs.rs index 49a5f1b..c94fa7e 100644 --- a/targets/otlp/src/logs.rs +++ b/targets/otlp/src/logs.rs @@ -70,7 +70,7 @@ impl emit_core::target::Target for OtlpLogsTarget { let observed_time_unix_nano = time_unix_nano; - let level = evt.props().lvl().unwrap_or(emit_core::level::Level::Info); + let level = evt.lvl().unwrap_or(emit_core::level::Level::Info); let severity_number = match level { emit_core::level::Level::Debug => SeverityNumber::Debug as i32,