diff options
Diffstat (limited to '')
-rw-r--r-- | vendor/tracing-core/src/span.rs | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/vendor/tracing-core/src/span.rs b/vendor/tracing-core/src/span.rs new file mode 100644 index 000000000..44738b290 --- /dev/null +++ b/vendor/tracing-core/src/span.rs @@ -0,0 +1,341 @@ +//! Spans represent periods of time in the execution of a program. +use crate::field::FieldSet; +use crate::parent::Parent; +use crate::stdlib::num::NonZeroU64; +use crate::{field, Metadata}; + +/// Identifies a span within the context of a subscriber. +/// +/// They are generated by [`Subscriber`]s for each span as it is created, by +/// the [`new_span`] trait method. See the documentation for that method for +/// more information on span ID generation. +/// +/// [`Subscriber`]: super::subscriber::Subscriber +/// [`new_span`]: super::subscriber::Subscriber::new_span +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct Id(NonZeroU64); + +/// Attributes provided to a `Subscriber` describing a new span when it is +/// created. +#[derive(Debug)] +pub struct Attributes<'a> { + metadata: &'static Metadata<'static>, + values: &'a field::ValueSet<'a>, + parent: Parent, +} + +/// A set of fields recorded by a span. +#[derive(Debug)] +pub struct Record<'a> { + values: &'a field::ValueSet<'a>, +} + +/// Indicates what [the `Subscriber` considers] the "current" span. +/// +/// As subscribers may not track a notion of a current span, this has three +/// possible states: +/// - "unknown", indicating that the subscriber does not track a current span, +/// - "none", indicating that the current context is known to not be in a span, +/// - "some", with the current span's [`Id`] and [`Metadata`]. +/// +/// [the `Subscriber` considers]: super::subscriber::Subscriber::current_span +/// [`Metadata`]: super::metadata::Metadata +#[derive(Debug)] +pub struct Current { + inner: CurrentInner, +} + +#[derive(Debug)] +enum CurrentInner { + Current { + id: Id, + metadata: &'static Metadata<'static>, + }, + None, + Unknown, +} + +// ===== impl Span ===== + +impl Id { + /// Constructs a new span ID from the given `u64`. + /// + /// <pre class="ignore" style="white-space:normal;font:inherit;"> + /// <strong>Note</strong>: Span IDs must be greater than zero. + /// </pre> + /// + /// # Panics + /// - If the provided `u64` is 0. + pub fn from_u64(u: u64) -> Self { + Id(NonZeroU64::new(u).expect("span IDs must be > 0")) + } + + /// Constructs a new span ID from the given `NonZeroU64`. + /// + /// Unlike [`Id::from_u64`](Id::from_u64()), this will never panic. + #[inline] + pub const fn from_non_zero_u64(id: NonZeroU64) -> Self { + Id(id) + } + + // Allow `into` by-ref since we don't want to impl Copy for Id + #[allow(clippy::wrong_self_convention)] + /// Returns the span's ID as a `u64`. + pub fn into_u64(&self) -> u64 { + self.0.get() + } + + // Allow `into` by-ref since we don't want to impl Copy for Id + #[allow(clippy::wrong_self_convention)] + /// Returns the span's ID as a `NonZeroU64`. + #[inline] + pub const fn into_non_zero_u64(&self) -> NonZeroU64 { + self.0 + } +} + +impl<'a> From<&'a Id> for Option<Id> { + fn from(id: &'a Id) -> Self { + Some(id.clone()) + } +} + +// ===== impl Attributes ===== + +impl<'a> Attributes<'a> { + /// Returns `Attributes` describing a new child span of the current span, + /// with the provided metadata and values. + pub fn new(metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>) -> Self { + Attributes { + metadata, + values, + parent: Parent::Current, + } + } + + /// Returns `Attributes` describing a new span at the root of its own trace + /// tree, with the provided metadata and values. + pub fn new_root(metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>) -> Self { + Attributes { + metadata, + values, + parent: Parent::Root, + } + } + + /// Returns `Attributes` describing a new child span of the specified + /// parent span, with the provided metadata and values. + pub fn child_of( + parent: Id, + metadata: &'static Metadata<'static>, + values: &'a field::ValueSet<'a>, + ) -> Self { + Attributes { + metadata, + values, + parent: Parent::Explicit(parent), + } + } + + /// Returns a reference to the new span's metadata. + pub fn metadata(&self) -> &'static Metadata<'static> { + self.metadata + } + + /// Returns a reference to a `ValueSet` containing any values the new span + /// was created with. + pub fn values(&self) -> &field::ValueSet<'a> { + self.values + } + + /// Returns true if the new span should be a root. + pub fn is_root(&self) -> bool { + matches!(self.parent, Parent::Root) + } + + /// Returns true if the new span's parent should be determined based on the + /// current context. + /// + /// If this is true and the current thread is currently inside a span, then + /// that span should be the new span's parent. Otherwise, if the current + /// thread is _not_ inside a span, then the new span will be the root of its + /// own trace tree. + pub fn is_contextual(&self) -> bool { + matches!(self.parent, Parent::Current) + } + + /// Returns the new span's explicitly-specified parent, if there is one. + /// + /// Otherwise (if the new span is a root or is a child of the current span), + /// returns `None`. + pub fn parent(&self) -> Option<&Id> { + match self.parent { + Parent::Explicit(ref p) => Some(p), + _ => None, + } + } + + /// Records all the fields in this set of `Attributes` with the provided + /// [Visitor]. + /// + /// [visitor]: super::field::Visit + pub fn record(&self, visitor: &mut dyn field::Visit) { + self.values.record(visitor) + } + + /// Returns `true` if this set of `Attributes` contains a value for the + /// given `Field`. + pub fn contains(&self, field: &field::Field) -> bool { + self.values.contains(field) + } + + /// Returns true if this set of `Attributes` contains _no_ values. + pub fn is_empty(&self) -> bool { + self.values.is_empty() + } + + /// Returns the set of all [fields] defined by this span's [`Metadata`]. + /// + /// Note that the [`FieldSet`] returned by this method includes *all* the + /// fields declared by this span, not just those with values that are recorded + /// as part of this set of `Attributes`. Other fields with values not present in + /// this `Attributes`' value set may [record] values later. + /// + /// [fields]: crate::field + /// [record]: Attributes::record() + /// [`Metadata`]: crate::metadata::Metadata + /// [`FieldSet`]: crate::field::FieldSet + pub fn fields(&self) -> &FieldSet { + self.values.field_set() + } +} + +// ===== impl Record ===== + +impl<'a> Record<'a> { + /// Constructs a new `Record` from a `ValueSet`. + pub fn new(values: &'a field::ValueSet<'a>) -> Self { + Self { values } + } + + /// Records all the fields in this `Record` with the provided [Visitor]. + /// + /// [visitor]: super::field::Visit + pub fn record(&self, visitor: &mut dyn field::Visit) { + self.values.record(visitor) + } + + /// Returns the number of fields that would be visited from this `Record` + /// when [`Record::record()`] is called + /// + /// [`Record::record()`]: Record::record() + pub fn len(&self) -> usize { + self.values.len() + } + + /// Returns `true` if this `Record` contains a value for the given `Field`. + pub fn contains(&self, field: &field::Field) -> bool { + self.values.contains(field) + } + + /// Returns true if this `Record` contains _no_ values. + pub fn is_empty(&self) -> bool { + self.values.is_empty() + } +} + +// ===== impl Current ===== + +impl Current { + /// Constructs a new `Current` that indicates the current context is a span + /// with the given `metadata` and `metadata`. + pub fn new(id: Id, metadata: &'static Metadata<'static>) -> Self { + Self { + inner: CurrentInner::Current { id, metadata }, + } + } + + /// Constructs a new `Current` that indicates the current context is *not* + /// in a span. + pub fn none() -> Self { + Self { + inner: CurrentInner::None, + } + } + + /// Constructs a new `Current` that indicates the `Subscriber` does not + /// track a current span. + pub(crate) fn unknown() -> Self { + Self { + inner: CurrentInner::Unknown, + } + } + + /// Returns `true` if the `Subscriber` that constructed this `Current` tracks a + /// current span. + /// + /// If this returns `true` and [`id`], [`metadata`], or [`into_inner`] + /// return `None`, that indicates that we are currently known to *not* be + /// inside a span. If this returns `false`, those methods will also return + /// `None`, but in this case, that is because the subscriber does not keep + /// track of the currently-entered span. + /// + /// [`id`]: Current::id() + /// [`metadata`]: Current::metadata() + /// [`into_inner`]: Current::into_inner() + pub fn is_known(&self) -> bool { + !matches!(self.inner, CurrentInner::Unknown) + } + + /// Consumes `self` and returns the span `Id` and `Metadata` of the current + /// span, if one exists and is known. + pub fn into_inner(self) -> Option<(Id, &'static Metadata<'static>)> { + match self.inner { + CurrentInner::Current { id, metadata } => Some((id, metadata)), + _ => None, + } + } + + /// Borrows the `Id` of the current span, if one exists and is known. + pub fn id(&self) -> Option<&Id> { + match self.inner { + CurrentInner::Current { ref id, .. } => Some(id), + _ => None, + } + } + + /// Borrows the `Metadata` of the current span, if one exists and is known. + pub fn metadata(&self) -> Option<&'static Metadata<'static>> { + match self.inner { + CurrentInner::Current { metadata, .. } => Some(metadata), + _ => None, + } + } +} + +impl<'a> From<&'a Current> for Option<&'a Id> { + fn from(cur: &'a Current) -> Self { + cur.id() + } +} + +impl<'a> From<&'a Current> for Option<Id> { + fn from(cur: &'a Current) -> Self { + cur.id().cloned() + } +} + +impl From<Current> for Option<Id> { + fn from(cur: Current) -> Self { + match cur.inner { + CurrentInner::Current { id, .. } => Some(id), + _ => None, + } + } +} + +impl<'a> From<&'a Current> for Option<&'static Metadata<'static>> { + fn from(cur: &'a Current) -> Self { + cur.metadata() + } +} |