trace: Make Span API functions taking IDs a little more flexible (#1021)

This branch modifies the `tokio_trace::Span` API functions that take
span IDs (the `Span::child_of` constructor, and the `Span::follows_from`
method) so that more types bearing a span ID can be passed as an
argument. Span IDs may now be passed directly without requiring them to
be passed as `Some(id)`. This should make the API slightly more
ergonomic.

Also, it changes the `Span::field` method to take an `AsField` rather
than a `Borrow<str>`.

Signed-off-by: Eliza Weisman <[email protected]>
This commit is contained in:
Eliza Weisman
2019-04-01 11:42:29 -07:00
committed by GitHub
parent 824b7b6759
commit 6c9d8abba9
+70 -18
View File
@@ -126,12 +126,16 @@
pub use tokio_trace_core::span::{Attributes, Id, Record}; pub use tokio_trace_core::span::{Attributes, Id, Record};
use std::{ use std::{
borrow::Borrow,
cmp, fmt, cmp, fmt,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
}; };
use {dispatcher::Dispatch, field, Metadata}; use {dispatcher::Dispatch, field, Metadata};
/// Trait implemented by types which have a span `Id`.
pub trait AsId: ::sealed::Sealed {
fn as_id(&self) -> Option<&Id>;
}
/// A handle representing a span, with the capability to enter the span if it /// A handle representing a span, with the capability to enter the span if it
/// exists. /// exists.
/// ///
@@ -229,10 +233,10 @@ impl Span {
values: &field::ValueSet, values: &field::ValueSet,
) -> Span ) -> Span
where where
I: Into<Option<Id>>, I: AsId,
{ {
let new_span = match parent.into() { let new_span = match parent.as_id() {
Some(parent) => Attributes::child_of(parent, meta, values), Some(parent) => Attributes::child_of(parent.clone(), meta, values),
None => Attributes::new_root(meta, values), None => Attributes::new_root(meta, values),
}; };
Self::make(meta, new_span) Self::make(meta, new_span)
@@ -280,22 +284,21 @@ impl Span {
/// Returns a [`Field`](::field::Field) for the field with the given `name`, if /// Returns a [`Field`](::field::Field) for the field with the given `name`, if
/// one exists, /// one exists,
pub fn field<Q>(&self, name: &Q) -> Option<field::Field> pub fn field<Q: ?Sized>(&self, field: &Q) -> Option<field::Field>
where where
Q: Borrow<str>, Q: field::AsField,
{ {
self.metadata().and_then(|meta| meta.fields().field(name)) self.metadata().and_then(|meta| field.as_field(meta))
} }
/// Returns true if this `Span` has a field for the given /// Returns true if this `Span` has a field for the given
/// [`Field`](::field::Field) or field name. /// [`Field`](::field::Field) or field name.
#[inline]
pub fn has_field<Q: ?Sized>(&self, field: &Q) -> bool pub fn has_field<Q: ?Sized>(&self, field: &Q) -> bool
where where
Q: field::AsField, Q: field::AsField,
{ {
self.metadata() self.field(field).is_some()
.and_then(|meta| field.as_field(meta))
.is_some()
} }
/// Visits that the field described by `field` has the value `value`. /// Visits that the field described by `field` has the value `value`.
@@ -347,9 +350,14 @@ impl Span {
/// ///
/// If this span is disabled, or the resulting follows-from relationship /// If this span is disabled, or the resulting follows-from relationship
/// would be invalid, this function will do nothing. /// would be invalid, this function will do nothing.
pub fn follows_from(&self, from: &Id) -> &Self { pub fn follows_from<I>(&self, from: I) -> &Self
where
I: AsId,
{
if let Some(ref inner) = self.inner { if let Some(ref inner) = self.inner {
inner.follows_from(from); if let Some(from) = from.as_id() {
inner.follows_from(from);
}
} }
self self
} }
@@ -436,12 +444,6 @@ impl fmt::Debug for Span {
} }
} }
impl<'a> Into<Option<Id>> for &'a Span {
fn into(self) -> Option<Id> {
self.id()
}
}
// ===== impl Inner ===== // ===== impl Inner =====
impl Inner { impl Inner {
@@ -553,3 +555,53 @@ impl<'a> fmt::Display for FmtAttrs<'a> {
res res
} }
} }
// ===== impl AsId =====
impl ::sealed::Sealed for Span {}
impl AsId for Span {
fn as_id(&self) -> Option<&Id> {
self.inner.as_ref().map(|inner| &inner.id)
}
}
impl<'a> ::sealed::Sealed for &'a Span {}
impl<'a> AsId for &'a Span {
fn as_id(&self) -> Option<&Id> {
self.inner.as_ref().map(|inner| &inner.id)
}
}
impl ::sealed::Sealed for Id {}
impl AsId for Id {
fn as_id(&self) -> Option<&Id> {
Some(self)
}
}
impl<'a> ::sealed::Sealed for &'a Id {}
impl<'a> AsId for &'a Id {
fn as_id(&self) -> Option<&Id> {
Some(self)
}
}
impl ::sealed::Sealed for Option<Id> {}
impl AsId for Option<Id> {
fn as_id(&self) -> Option<&Id> {
self.as_ref()
}
}
impl<'a> ::sealed::Sealed for &'a Option<Id> {}
impl<'a> AsId for &'a Option<Id> {
fn as_id(&self) -> Option<&Id> {
self.as_ref()
}
}