Skip to content
This repository has been archived by the owner on Jun 8, 2024. It is now read-only.

Commit

Permalink
work on unifying spans and logs
Browse files Browse the repository at this point in the history
  • Loading branch information
KodrAus committed Jul 27, 2023
1 parent eefe943 commit d217e5b
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 54 deletions.
41 changes: 10 additions & 31 deletions core/src/event.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
use core::{
fmt,
ops::{ControlFlow, RangeInclusive},
};
use core::{fmt, ops::ControlFlow};

use crate::{
key::{Key, ToKey},
props::{ByRef, Chain, ErasedProps, Props},
template::{Render, Template},
time::Timestamp,
time::Extent,
value::{ToValue, Value},
well_known::{MESSAGE_KEY, TEMPLATE_KEY, TIMESTAMP_KEY, TIMESTAMP_START_KEY},
};

#[derive(Clone)]
pub struct Event<'a, P> {
ts: Option<RangeInclusive<Timestamp>>,
ts: Option<Extent>,
tpl: Template<'a>,
props: P,
}
Expand All @@ -34,17 +31,9 @@ impl<'a, P: Props> fmt::Debug for Event<'a, P> {
}

impl<'a, P: Props> Event<'a, P> {
pub fn point(ts: impl Into<Option<Timestamp>>, tpl: Template<'a>, props: P) -> Self {
Event::spanned(ts.into().map(|ts| ts..=ts), tpl, props)
}

pub fn spanned(
ts: impl Into<Option<RangeInclusive<Timestamp>>>,
tpl: Template<'a>,
props: P,
) -> Self {
pub fn new(ts: Option<impl Into<Extent>>, tpl: Template<'a>, props: P) -> Self {
Event {
ts: ts.into(),
ts: ts.map(Into::into),
tpl,
props,
}
Expand All @@ -58,18 +47,8 @@ impl<'a, P: Props> Event<'a, P> {
self.tpl.by_ref()
}

pub fn timestamp(&self) -> Option<Timestamp> {
self.ts.as_ref().map(|ts| *ts.start())
}

pub fn timespan(&self) -> Option<RangeInclusive<Timestamp>> {
self.ts.as_ref().and_then(|ts| {
if *ts.start() != *ts.end() {
Some(ts.clone())
} else {
None
}
})
pub fn extent(&self) -> Option<&Extent> {
self.ts.as_ref()
}

pub fn chain<U: Props>(self, other: U) -> Event<'a, Chain<P, U>> {
Expand Down Expand Up @@ -111,7 +90,7 @@ impl<'a, P: Props> Event<'a, P> {
}

pub struct AllProps<'a, P> {
ts: Option<RangeInclusive<Timestamp>>,
ts: Option<Extent>,
tpl: Template<'a>,
msg: Render<'a, &'a P>,
props: ByRef<'a, P>,
Expand All @@ -123,8 +102,8 @@ impl<'a, P: Props> Props for AllProps<'a, P> {
mut for_each: F,
) {
if let Some(ref ts) = self.ts {
if *ts.start() != *ts.end() {
for_each(TIMESTAMP_START_KEY.to_key(), ts.start().to_value());
if let Some(start) = ts.start() {
for_each(TIMESTAMP_START_KEY.to_key(), start.to_value());
}

for_each(TIMESTAMP_KEY.to_key(), ts.end().to_value());
Expand Down
1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#[cfg(feature = "alloc")]
extern crate alloc;
extern crate core;

pub mod ambient;
pub mod ctxt;
Expand Down
73 changes: 72 additions & 1 deletion core/src/time.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use core::{cmp, fmt, str, str::FromStr, time::Duration};
use core::{cmp, fmt, ops::RangeInclusive, str, str::FromStr, time::Duration};

use crate::{
empty::Empty,
Expand Down Expand Up @@ -57,6 +57,77 @@ impl<'v> Value<'v> {
}
}

#[derive(Clone)]
pub struct Extent(ExtentInner);

#[derive(Clone)]
enum ExtentInner {
Point(Timestamp),
Span(RangeInclusive<Timestamp>),
}

impl fmt::Debug for Extent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
ExtentInner::Point(ts) => fmt::Debug::fmt(&ts, f),
ExtentInner::Span(ref ts) => fmt::Debug::fmt(ts, f),
}
}
}

impl fmt::Display for Extent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
ExtentInner::Point(ts) => fmt::Display::fmt(&ts, f),
ExtentInner::Span(ref ts) => {
fmt::Display::fmt(ts.start(), f)?;
write!(f, "..=")?;
fmt::Display::fmt(ts.end(), f)
}
}
}
}

impl Extent {
pub fn point(ts: Timestamp) -> Extent {
Extent(ExtentInner::Point(ts))
}

pub fn span(ts: RangeInclusive<Timestamp>) -> Extent {
if ts.start() == ts.end() {
Extent::point(*ts.end())
} else {
Extent(ExtentInner::Span(ts))
}
}

pub fn start(&self) -> Option<&Timestamp> {
match self.0 {
ExtentInner::Point(_) => None,
ExtentInner::Span(ref ts) => Some(ts.start()),
}
}

pub fn end(&self) -> &Timestamp {
match self.0 {
ExtentInner::Point(ref ts) => ts,
ExtentInner::Span(ref ts) => ts.end(),
}
}
}

impl From<Timestamp> for Extent {
fn from(point: Timestamp) -> Extent {
Extent::point(point)
}
}

impl From<RangeInclusive<Timestamp>> for Extent {
fn from(span: RangeInclusive<Timestamp>) -> Extent {
Extent::span(span)
}
}

pub trait Clock {
fn now(&self) -> Option<Timestamp>;
}
Expand Down
9 changes: 8 additions & 1 deletion macros/src/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,26 @@ pub struct ExpandTokens {
}

struct Args {
ts: TokenStream,
to: TokenStream,
when: TokenStream,
}

impl Parse for Args {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let mut ts = Arg::token_stream("ts", |expr| {
Ok(quote!(Some(emit::time::Extent::from(#expr))))
});
let mut to = Arg::token_stream("to", |expr| Ok(quote!(#expr)));
let mut when = Arg::token_stream("when", |expr| Ok(quote!(#expr)));

args::set_from_field_values(
input.parse_terminated(FieldValue::parse, Token![,])?.iter(),
[&mut to, &mut when],
[&mut ts, &mut to, &mut when],
)?;

Ok(Args {
ts: ts.take().unwrap_or_else(|| quote!(None)),
to: to.take().unwrap_or_else(|| quote!(emit::empty::Empty)),
when: when.take().unwrap_or_else(|| quote!(emit::empty::Empty)),
})
Expand All @@ -46,6 +51,7 @@ pub fn expand_tokens(opts: ExpandTokens) -> Result<TokenStream, syn::Error> {
let props_match_binding_tokens = props.match_binding_tokens();
let props_tokens = props.match_bound_tokens();

let ts_tokens = args.ts;
let to_tokens = args.to;
let when_tokens = args.when;

Expand All @@ -64,6 +70,7 @@ pub fn expand_tokens(opts: ExpandTokens) -> Result<TokenStream, syn::Error> {
emit::#receiver_tokens(
#to_tokens,
#when_tokens,
#ts_tokens,
#level_tokens,
#template_tokens,
#props_tokens,
Expand Down
3 changes: 2 additions & 1 deletion macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mod fmt;
mod hook;
mod key;
mod props;
mod span;
mod template;
mod util;
mod with;
Expand Down Expand Up @@ -67,7 +68,7 @@ Format a template.
#[proc_macro]
pub fn format(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
emit::expand_tokens(emit::ExpandTokens {
receiver: quote!(format),
receiver: quote!(__private::__format),
level: quote!(default()),
input: TokenStream::from(item),
})
Expand Down
1 change: 1 addition & 0 deletions macros/src/span.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

26 changes: 17 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
extern crate alloc;

use core::future::Future;
use std::ops::RangeInclusive;

use emit_core::{ctxt::Ctxt, filter::Filter, target::Target, time::Clock};
use emit_core::{ctxt::Ctxt, filter::Filter, target::Target};

#[doc(inline)]
pub use emit_macros::*;
Expand All @@ -21,7 +22,11 @@ pub mod ctxt {
pub use emit_core::ctxt::*;
}

use emit_core::{value::ToValue, well_known::WellKnown};
use emit_core::{
time::{Clock, Extent},
value::ToValue,
well_known::WellKnown,
};

pub use self::{
event::Event, key::Key, level::Level, props::Props, template::Template, time::Timestamp,
Expand All @@ -42,13 +47,18 @@ mod setup;
pub fn emit(evt: &Event<impl Props>) {
let ambient = emit_core::ambient::get();

let tpl = evt.template();
let props = evt.props();

base_emit(
ambient,
ambient,
ambient,
ambient,
evt.template(),
evt.props(),
evt.extent()
.cloned()
.or_else(|| ambient.now().map(Extent::point)),
tpl,
props,
);
}

Expand All @@ -57,14 +67,12 @@ fn base_emit(
to: impl Target,
when: impl Filter,
ctxt: impl Ctxt,
clock: impl Clock,
ts: Option<Extent>,
tpl: Template,
props: impl Props,
) {
ctxt.with_current(|ctxt| {
let ts = clock.now();

let evt = Event::point(ts, tpl, props.chain(ctxt));
let evt = Event::new(ts, tpl, props.chain(ctxt));

if when.matches(&evt) {
to.event(&evt);
Expand Down
23 changes: 14 additions & 9 deletions src/macro_hooks.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
use core::{any::Any, fmt};

use emit_core::value::{ToValue, Value};
use core::{any::Any, fmt, future::Future};

use emit_core::{
ambient,
ctxt::Ctxt,
filter::Filter,
id::IdSource,
level::Level,
props::Props,
target::Target,
template::Template,
time::Clock,
well_known::{WellKnown, LEVEL_KEY},
time::{Clock, Extent},
value::Value,
well_known::LEVEL_KEY,
};

#[cfg(feature = "std")]
use std::error::Error;
use std::future::Future;

use crate::{
base_emit, base_with, base_with_future,
Expand Down Expand Up @@ -302,14 +300,21 @@ impl<'a> __PrivateKeyHook for Key<'a> {
}

#[track_caller]
pub fn __emit(to: impl Target, when: impl Filter, lvl: Level, tpl: Template, props: impl Props) {
pub fn __emit(
to: impl Target,
when: impl Filter,
ts: Option<Extent>,
lvl: Level,
tpl: Template,
props: impl Props,
) {
let ambient = ambient::get();

base_emit(
to.and(ambient),
when.and(ambient),
ambient,
ambient,
ts.or_else(|| ambient.now().map(Extent::point)),
tpl,
(LEVEL_KEY, lvl).chain(props),
);
Expand Down
3 changes: 2 additions & 1 deletion targets/otlp/src/logs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ impl OtlpLogsTargetBuilder {
impl emit_core::target::Target for OtlpLogsTarget {
fn event<P: emit_core::props::Props>(&self, evt: &emit_core::event::Event<P>) {
let time_unix_nano = evt
.timestamp()
.extent()
.map(|ts| ts.end())
.map(|ts| ts.to_unix().as_nanos() as u64)
.unwrap_or_default();

Expand Down
2 changes: 1 addition & 1 deletion targets/term/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl emit::target::Target for Stdout {
fn print(out: &BufferWriter, buf: &mut Buffer, evt: &emit::Event<impl emit::Props>) {
let mut header_empty = true;

if let Some(ts) = evt.timestamp() {
if let Some(ts) = evt.extent() {
let _ = write!(buf, "[{:.0}", ts);

header_empty = false;
Expand Down

0 comments on commit d217e5b

Please sign in to comment.