trace: Allow specifying a new span's parent (#923)

This branch allows users of `tokio-trace` to explicitly set a span's
parent, or indicate that a span should be a new root of its own trace
tree. A `parent: ` key has been added to the `span!` macros. When a span
is provided, that span will be set as the parent, while `parent: None`
will result in a new root span. No `parent:` key results in the current
behaviour.

A new type, `span::Attributes`, was added to `tokio-trace-core` to act
as an arguments struct for the `Subscriber::new_span` method. This will
allow future fields to be added without causing breaking API changes.
The `Attributes` struct currently contains the new span's metadata,
`ValueSet`, and parent.

Finally, the `span::Span` type in `-core` was renamed to `span::Id`, for
consistency with `tokio-trace` and to differentiate it from
`span::Attributes`. This name was chosen primarily due to precedent in
other tracing systems.

Closes #920 

Signed-off-by: Eliza Weisman <[email protected]>
This commit is contained in:
Eliza Weisman
2019-03-01 11:29:11 -08:00
committed by GitHub
parent 43d69d77e2
commit 5ff6e37c59
15 changed files with 671 additions and 103 deletions
+151 -10
View File
@@ -247,9 +247,9 @@
//! #[macro_use]
//! extern crate tokio_trace;
//! # pub struct FooSubscriber;
//! # use tokio_trace::{span::Id, Metadata, field::ValueSet};
//! # use tokio_trace::{span::{Id, Attributes}, Metadata, field::ValueSet};
//! # impl tokio_trace::Subscriber for FooSubscriber {
//! # fn new_span(&self, _: &Metadata, _: &ValueSet) -> Id { Id::from_u64(0) }
//! # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) }
//! # fn record(&self, _: &Id, _: &ValueSet) {}
//! # fn event(&self, _: &tokio_trace::Event) {}
//! # fn record_follows_from(&self, _: &Id, _: &Id) {}
@@ -488,12 +488,30 @@ macro_rules! callsite {
/// ```
#[macro_export]
macro_rules! span {
(target: $target:expr, level: $lvl:expr, $name:expr, $($k:ident $( = $val:expr )* ),*,) => {
span!(target: $target, level: $lvl, $name, $($k $( = $val)*),*)
(
target: $target:expr,
level: $lvl:expr,
parent: $parent:expr,
$name:expr,
$($k:ident $( = $val:expr )* ),*,
) => {
span!(
target: $target,
level: $lvl,
parent: $parent,
$name,
$($k $( = $val)*),*
)
};
(target: $target:expr, level: $lvl:expr, $name:expr, $($k:ident $( = $val:expr )* ),*) => {
(
target: $target:expr,
level: $lvl:expr,
parent: $parent:expr,
$name:expr,
$($k:ident $( = $val:expr )* ),*
) => {
{
use $crate::{callsite, field::{Value, ValueSet, AsField}, Span};
use $crate::callsite;
use $crate::callsite::Callsite;
let callsite = callsite! {
name: $name,
@@ -503,17 +521,135 @@ macro_rules! span {
};
if is_enabled!(callsite) {
let meta = callsite.metadata();
Span::new(meta, &valueset!(meta.fields(), $($k $( = $val)*),*))
$crate::Span::child_of(
$parent,
meta,
&valueset!(meta.fields(), $($k $( = $val)*),*),
)
} else {
Span::new_disabled()
$crate::Span::new_disabled()
}
}
};
(
target: $target:expr,
level: $lvl:expr,
$name:expr,
$($k:ident $( = $val:expr )* ),*
) => {
{
use $crate::callsite;
use $crate::callsite::Callsite;
let callsite = callsite! {
name: $name,
target: $target,
level: $lvl,
fields: $($k),*
};
if is_enabled!(callsite) {
let meta = callsite.metadata();
$crate::Span::new(
meta,
&valueset!(meta.fields(), $($k $( = $val)*),*),
)
} else {
$crate::Span::new_disabled()
}
}
};
(target: $target:expr, level: $lvl:expr, parent: $parent:expr, $name:expr) => {
span!(target: $target, level: $lvl, parent: $parent, $name,)
};
(level: $lvl:expr, parent: $parent:expr, $name:expr, $($k:ident $( = $val:expr )* ),*,) => {
span!(
target: module_path!(),
level: $lvl,
parent: $parent,
$name,
$($k $( = $val)*),*
)
};
(level: $lvl:expr, parent: $parent:expr, $name:expr, $($k:ident $( = $val:expr )* ),*) => {
span!(
target: module_path!(),
level: $lvl,
parent: $parent,
$name,
$($k $( = $val)*),*
)
};
(level: $lvl:expr, parent: $parent:expr, $name:expr) => {
span!(target: module_path!(), level: $lvl, parent: $parent, $name,)
};
(parent: $parent:expr, $name:expr, $($k:ident $( = $val:expr)*),*,) => {
span!(
target: module_path!(),
level: $crate::Level::TRACE,
parent: $parent,
$name,
$($k $( = $val)*),*
)
};
(parent: $parent:expr, $name:expr, $($k:ident $( = $val:expr)*),*) => {
span!(
target: module_path!(),
level: $crate::Level::TRACE,
parent: $parent,
$name,
$($k $( = $val)*),*
)
};
(parent: $parent:expr, $name:expr) => {
span!(
target: module_path!(),
level: $crate::Level::TRACE,
parent: $parent,
$name,
)
};
(
target: $target:expr,
level: $lvl:expr,
$name:expr,
$($k:ident $( = $val:expr )* ),*,
) => {
span!(
target: $target,
level: $lvl,
$name,
$($k $( = $val)*),*
)
};
(
target: $target:expr,
level: $lvl:expr,
$name:expr,
$($k:ident $( = $val:expr )* ),*
) => {
span!(
target: $target,
level: $lvl,
$name,
$($k $( = $val)*),*
)
};
(target: $target:expr, level: $lvl:expr, $name:expr) => {
span!(target: $target, level: $lvl, $name,)
};
(target: $target:expr, level: $lvl:expr, $name:expr,) => {
span!(
target: $target,
level: $lvl,
$name,
)
};
(level: $lvl:expr, $name:expr, $($k:ident $( = $val:expr )* ),*,) => {
span!(target: module_path!(), level: $lvl, $name, $($k $( = $val)*),*)
span!(
target: module_path!(),
level: $lvl,
$name,
$($k $( = $val)*),*
)
};
(level: $lvl:expr, $name:expr, $($k:ident $( = $val:expr )* ),*) => {
span!(target: module_path!(), level: $lvl, $name, $($k $( = $val)*),*)
@@ -525,7 +661,12 @@ macro_rules! span {
span!(target: module_path!(), level: $crate::Level::TRACE, $name, $($k $( = $val)*),*)
};
($name:expr, $($k:ident $( = $val:expr)*),*) => {
span!(target: module_path!(), level: $crate::Level::TRACE, $name, $($k $( = $val)*),*)
span!(
target: module_path!(),
level: $crate::Level::TRACE,
$name,
$($k $( = $val)*),*
)
};
($name:expr) => { span!(target: module_path!(), level: $crate::Level::TRACE, $name,) };
}
+57 -11
View File
@@ -135,8 +135,7 @@
//! the data for future use, record it in some manner, or discard it completely.
//!
//! [`Subscriber`]: ::Subscriber
// TODO: remove this re-export?
pub use tokio_trace_core::span::Span as Id;
pub use tokio_trace_core::span::{Attributes, Id};
use std::{
borrow::Borrow,
@@ -209,7 +208,8 @@ struct Entered<'a> {
// ===== impl Span =====
impl<'a> Span<'a> {
/// Constructs a new `Span` with the given [metadata] and set of [field values].
/// Constructs a new `Span` with the given [metadata] and set of [field
/// values].
///
/// The new span will be constructed by the currently-active [`Subscriber`],
/// with the current span as its parent (if one exists).
@@ -223,14 +223,42 @@ impl<'a> Span<'a> {
/// [`follows_from`]: ::span::Span::follows_from
#[inline]
pub fn new(meta: &'a Metadata<'a>, values: &field::ValueSet) -> Span<'a> {
let inner = dispatcher::with(move |dispatch| {
let id = dispatch.new_span(meta, values);
Some(Inner::new(id, dispatch, meta))
});
Self {
inner,
is_closed: false,
}
let new_span = Attributes::new(meta, values);
Self::make(meta, new_span)
}
/// Constructs a new `Span` as the root of its own trace tree, with the
/// given [metadata] and set of [field values].
///
/// After the span is constructed, [field values] and/or [`follows_from`]
/// annotations may be added to it.
///
/// [metadata]: ::metadata::Metadata
/// [field values]: ::field::ValueSet
/// [`follows_from`]: ::span::Span::follows_from
#[inline]
pub fn new_root(meta: &'a Metadata<'a>, values: &field::ValueSet) -> Span<'a> {
Self::make(meta, Attributes::new_root(meta, values))
}
/// Constructs a new `Span` as child of the given parent span, with the
/// given [metadata] and set of [field values].
///
/// After the span is constructed, [field values] and/or [`follows_from`]
/// annotations may be added to it.
///
/// [metadata]: ::metadata::Metadata
/// [field values]: ::field::ValueSet
/// [`follows_from`]: ::span::Span::follows_from
pub fn child_of<I>(parent: I, meta: &'a Metadata<'a>, values: &field::ValueSet) -> Span<'a>
where
I: Into<Option<Id>>,
{
let new_span = match parent.into() {
Some(parent) => Attributes::child_of(parent, meta, values),
None => Attributes::new_root(meta, values),
};
Self::make(meta, new_span)
}
/// Constructs a new disabled span.
@@ -242,6 +270,18 @@ impl<'a> Span<'a> {
}
}
#[inline(always)]
fn make(meta: &'a Metadata<'a>, new_span: Attributes) -> Span<'a> {
let inner = dispatcher::with(move |dispatch| {
let id = dispatch.new_span(&new_span);
Some(Inner::new(id, dispatch, meta))
});
Self {
inner,
is_closed: false,
}
}
/// Executes the given function in the context of this span.
///
/// If this span is enabled, then this function enters the span, invokes
@@ -380,6 +420,12 @@ impl<'a> fmt::Debug for Span<'a> {
}
}
impl<'a> Into<Option<Id>> for &'a Span<'a> {
fn into(self) -> Option<Id> {
self.id()
}
}
// ===== impl Inner =====
impl<'a> Inner<'a> {