Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

trace: Span API polish #988

Merged
merged 5 commits into from
Mar 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tokio-trace/benches/subscriber.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ fn enter_span(b: &mut Bencher) {
#[bench]
fn span_repeatedly(b: &mut Bencher) {
#[inline]
fn mk_span(i: u64) -> tokio_trace::Span<'static> {
fn mk_span(i: u64) -> tokio_trace::Span {
span!("span", i = i)
}

Expand Down
120 changes: 30 additions & 90 deletions tokio-trace/src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@
//! # extern crate tokio_trace;
//! # extern crate futures;
//! # use futures::{Future, Poll, Async};
//! struct MyFuture<'a> {
//! struct MyFuture {
//! // data
//! span: tokio_trace::Span<'a>,
//! span: tokio_trace::Span,
//! }
//!
//! impl<'a> Future for MyFuture<'a> {
//! impl Future for MyFuture {
//! type Item = ();
//! type Error = ();
//!
Expand Down Expand Up @@ -91,29 +91,17 @@
//! # }
//! ```
//!
//! A span may be explicitly closed before when the span handle is dropped by
//! calling the [`Span::close`] method. Doing so will drop that handle the next
//! A span may be explicitly closed by dropping a handle to it, if it is the only
//! handle to that span.
//! time it is exited. For example:
//! ```
//! # #[macro_use] extern crate tokio_trace;
//! # fn main() {
//! use tokio_trace::Span;
//!
//! let mut my_span = span!("my_span");
//! // Signal to my_span that it should close when it exits
//! my_span.close();
//! my_span.enter(|| {
//! // ...
//! }); // --> Subscriber::exit(my_span); Subscriber::drop_span(my_span)
//!
//! // The handle to `my_span` still exists, but it now knows that the span was
//! // closed while it was executing.
//! my_span.is_closed(); // ==> true
//!
//! // Attempting to enter the span using the handle again will do nothing.
//! my_span.enter(|| {
//! // no-op
//! });
//! let my_span = span!("my_span");
//! // Drop the handle to the span.
//! drop(my_span); // --> Subscriber::drop_span(my_span)
//! # }
//! ```
//! However, if multiple handles exist, the span can still be re-entered even if
Expand Down Expand Up @@ -154,18 +142,11 @@ use {
/// span will silently do nothing. Thus, the handle can be used in the same
/// manner regardless of whether or not the trace is currently being collected.
#[derive(Clone, PartialEq, Hash)]
pub struct Span<'a> {
pub struct Span {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this means we can drop the lifetime from tokio_trace_futures::Instrumented?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes; in fact, this will break the current Instrumented.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works for me! its an easy upgrade

/// A handle used to enter the span when it is not executing.
///
/// If this is `None`, then the span has either closed or was never enabled.
inner: Option<Inner<'a>>,

/// Set to `true` when the span closes.
///
/// This allows us to distinguish if `inner` is `None` because the span was
/// never enabled (and thus the inner state was never created), or if the
/// previously entered, but it is now closed.
is_closed: bool,
inner: Option<Inner<'static>>,
}

/// A handle representing the capacity to enter a span which is known to exist.
Expand All @@ -184,10 +165,6 @@ pub(crate) struct Inner<'a> {
/// `id`.
subscriber: Dispatch,

/// A flag indicating that the span has been instructed to close when
/// possible.
closed: bool,

meta: &'a Metadata<'a>,
}

Expand All @@ -207,7 +184,7 @@ struct Entered<'a> {

// ===== impl Span =====

impl<'a> Span<'a> {
impl Span {
/// Constructs a new `Span` with the given [metadata] and set of [field
/// values].
///
Expand All @@ -222,7 +199,7 @@ impl<'a> Span<'a> {
/// [field values]: ::field::ValueSet
/// [`follows_from`]: ::span::Span::follows_from
#[inline]
pub fn new(meta: &'a Metadata<'a>, values: &field::ValueSet) -> Span<'a> {
pub fn new(meta: &'static Metadata<'static>, values: &field::ValueSet) -> Span {
let new_span = Attributes::new(meta, values);
Self::make(meta, new_span)
}
Expand All @@ -237,7 +214,7 @@ impl<'a> Span<'a> {
/// [field values]: ::field::ValueSet
/// [`follows_from`]: ::span::Span::follows_from
#[inline]
pub fn new_root(meta: &'a Metadata<'a>, values: &field::ValueSet) -> Span<'a> {
pub fn new_root(meta: &'static Metadata<'static>, values: &field::ValueSet) -> Span {
Self::make(meta, Attributes::new_root(meta, values))
}

Expand All @@ -250,7 +227,11 @@ impl<'a> Span<'a> {
/// [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>
pub fn child_of<I>(
parent: I,
meta: &'static Metadata<'static>,
values: &field::ValueSet,
) -> Span
where
I: Into<Option<Id>>,
{
Expand All @@ -263,23 +244,17 @@ impl<'a> Span<'a> {

/// Constructs a new disabled span.
#[inline(always)]
pub fn new_disabled() -> Span<'a> {
Span {
inner: None,
is_closed: false,
}
pub fn new_disabled() -> Span {
Span { inner: None }
}

#[inline(always)]
fn make(meta: &'a Metadata<'a>, new_span: Attributes) -> Span<'a> {
fn make(meta: &'static Metadata<'static>, new_span: Attributes) -> Span {
let inner = dispatcher::get_default(move |dispatch| {
let id = dispatch.new_span(&new_span);
Some(Inner::new(id, dispatch, meta))
});
Self {
inner,
is_closed: false,
}
Self { inner }
}

/// Executes the given function in the context of this span.
Expand All @@ -295,7 +270,7 @@ impl<'a> Span<'a> {
Some(inner) => {
let guard = inner.enter();
let result = f();
self.inner = guard.exit();
self.inner = Some(guard.exit());
result
}
None => f(),
Expand Down Expand Up @@ -351,29 +326,11 @@ impl<'a> Span<'a> {
self
}

/// Closes this span handle, dropping its internal state.
///
/// Once this function has been called, subsequent calls to `enter` on this
/// handle will no longer enter the span. If this is the final handle with
/// the potential to enter that span, the subscriber may consider the span to
/// have ended.
pub fn close(&mut self) {
if let Some(mut inner) = self.inner.take() {
inner.close();
}
self.is_closed = true;
}

/// Returns `true` if this span is closed.
pub fn is_closed(&self) -> bool {
self.is_closed
}

/// Returns `true` if this span was disabled by the subscriber and does not
/// exist.
#[inline]
pub fn is_disabled(&self) -> bool {
self.inner.is_none() && !self.is_closed
self.inner.is_none()
}

/// Indicates that the span with the given ID has an indirect causal
Expand Down Expand Up @@ -403,12 +360,12 @@ impl<'a> Span<'a> {
}

/// Returns this span's `Metadata`, if it is enabled.
pub fn metadata(&self) -> Option<&'a Metadata<'a>> {
pub fn metadata(&self) -> Option<&'static Metadata<'static>> {
self.inner.as_ref().map(Inner::metadata)
}
}

impl<'a> fmt::Debug for Span<'a> {
impl<'a> fmt::Debug for Span {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut span = f.debug_struct("Span");
if let Some(ref inner) = self.inner {
Expand All @@ -420,7 +377,7 @@ impl<'a> fmt::Debug for Span<'a> {
}
}

impl<'a> Into<Option<Id>> for &'a Span<'a> {
impl<'a> Into<Option<Id>> for &'a Span {
fn into(self) -> Option<Id> {
self.id()
}
Expand All @@ -429,14 +386,6 @@ impl<'a> Into<Option<Id>> for &'a Span<'a> {
// ===== impl Inner =====

impl<'a> Inner<'a> {
/// Indicates that this handle will not be reused to enter the span again.
///
/// After calling `close`, the `Entered` guard returned by `self.enter()`
/// will _drop_ this handle when it is exited.
fn close(&mut self) {
self.closed = true;
}

/// Enters the span, returning a guard that may be used to exit the span and
/// re-enter the prior span.
///
Expand Down Expand Up @@ -487,7 +436,6 @@ impl<'a> Inner<'a> {
Inner {
id,
subscriber: subscriber.clone(),
closed: false,
meta,
}
}
Expand Down Expand Up @@ -516,7 +464,6 @@ impl<'a> Clone for Inner<'a> {
Inner {
id: self.subscriber.clone_span(&self.id),
subscriber: self.subscriber.clone(),
closed: self.closed,
meta: self.meta,
}
}
Expand All @@ -526,16 +473,9 @@ impl<'a> Clone for Inner<'a> {

impl<'a> Entered<'a> {
/// Exit the `Entered` guard, returning an `Inner` handle that may be used
/// to re-enter the span, or `None` if the span closed while performing the
/// exit.
fn exit(self) -> Option<Inner<'a>> {
/// to re-enter the span.
fn exit(self) -> Inner<'a> {
self.inner.subscriber.exit(&self.inner.id);
if self.inner.closed {
// Dropping `inner` will allow it to perform the closure if
// able.
None
} else {
Some(self.inner)
}
self.inner
}
}
57 changes: 2 additions & 55 deletions tokio-trace/tests/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,6 @@ use tokio_trace::{
Level, Span,
};

#[test]
fn closed_handle_cannot_be_entered() {
let subscriber = subscriber::mock()
.enter(span::mock().named("foo"))
.drop_span(span::mock().named("bar"))
.enter(span::mock().named("bar"))
.exit(span::mock().named("bar"))
.drop_span(span::mock().named("bar"))
.exit(span::mock().named("foo"))
.run();

with_default(subscriber, || {
span!("foo").enter(|| {
let bar = span!("bar");
let mut another_bar = bar.clone();
drop(bar);

another_bar.enter(|| {});

another_bar.close();
// After we close `another_bar`, it should close and not be
// re-entered.
another_bar.enter(|| {});
});
});
}

#[test]
fn handles_to_the_same_span_are_equal() {
// Create a mock subscriber that will return `true` on calls to
Expand Down Expand Up @@ -67,7 +40,7 @@ fn handles_to_different_spans_are_not_equal() {
fn handles_to_different_spans_with_the_same_metadata_are_not_equal() {
// Every time time this function is called, it will return a _new
// instance_ of a span with the same metadata, name, and fields.
fn make_span() -> Span<'static> {
fn make_span() -> Span {
span!("foo", bar = 1u64, baz = false)
}

Expand Down Expand Up @@ -272,36 +245,10 @@ fn span_closes_when_exited() {
.run_with_handle();
with_default(subscriber, || {
let mut foo = span!("foo");
assert!(!foo.is_closed());

foo.enter(|| {});
assert!(!foo.is_closed());

foo.close();
assert!(foo.is_closed());

// Now that `foo` has closed, entering it should do nothing.
foo.enter(|| {});
assert!(foo.is_closed());
});

handle.assert_finished();
}

#[test]
fn entering_a_closed_span_again_is_a_no_op() {
let (subscriber, handle) = subscriber::mock()
.drop_span(span::mock().named("foo"))
.done()
.run_with_handle();
with_default(subscriber, || {
let mut foo = span!("foo");

foo.close();
foo.enter(|| {
// This should do nothing.
});
assert!(foo.is_closed());
drop(foo);
});

handle.assert_finished();
Expand Down