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};
use std::{
borrow::Borrow,
cmp, fmt,
hash::{Hash, Hasher},
};
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
/// exists.
///
@@ -229,10 +233,10 @@ impl Span {
values: &field::ValueSet,
) -> Span
where
I: Into<Option<Id>>,
I: AsId,
{
let new_span = match parent.into() {
Some(parent) => Attributes::child_of(parent, meta, values),
let new_span = match parent.as_id() {
Some(parent) => Attributes::child_of(parent.clone(), meta, values),
None => Attributes::new_root(meta, values),
};
Self::make(meta, new_span)
@@ -280,22 +284,21 @@ impl Span {
/// Returns a [`Field`](::field::Field) for the field with the given `name`, if
/// one exists,
pub fn field<Q>(&self, name: &Q) -> Option<field::Field>
pub fn field<Q: ?Sized>(&self, field: &Q) -> Option<field::Field>
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
/// [`Field`](::field::Field) or field name.
#[inline]
pub fn has_field<Q: ?Sized>(&self, field: &Q) -> bool
where
Q: field::AsField,
{
self.metadata()
.and_then(|meta| field.as_field(meta))
.is_some()
self.field(field).is_some()
}
/// 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
/// 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 {
inner.follows_from(from);
if let Some(from) = from.as_id() {
inner.follows_from(from);
}
}
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 {
@@ -553,3 +555,53 @@ impl<'a> fmt::Display for FmtAttrs<'a> {
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()
}
}