//! Storage for span data shared by multiple [`Layer`]s. //! //! ## Using the Span Registry //! //! This module provides the [`Registry`] type, a [`Subscriber`] implementation //! which tracks per-span data and exposes it to [`Layer`]s. When a `Registry` //! is used as the base `Subscriber` of a `Layer` stack, the //! [`layer::Context`][ctx] type will provide methods allowing `Layer`s to //! [look up span data][lookup] stored in the registry. While [`Registry`] is a //! reasonable default for storing spans and events, other stores that implement //! [`LookupSpan`] and [`Subscriber`] themselves (with [`SpanData`] implemented //! by the per-span data they store) can be used as a drop-in replacement. //! //! For example, we might create a `Registry` and add multiple `Layer`s like so: //! ```rust //! use tracing_subscriber::{registry::Registry, Layer, prelude::*}; //! # use tracing_core::Subscriber; //! # pub struct FooLayer {} //! # pub struct BarLayer {} //! # impl<S: Subscriber> Layer<S> for FooLayer {} //! # impl<S: Subscriber> Layer<S> for BarLayer {} //! # impl FooLayer { //! # fn new() -> Self { Self {} } //! # } //! # impl BarLayer { //! # fn new() -> Self { Self {} } //! # } //! //! let subscriber = Registry::default() //! .with(FooLayer::new()) //! .with(BarLayer::new()); //! ``` //! //! If a type implementing `Layer` depends on the functionality of a `Registry` //! implementation, it should bound its `Subscriber` type parameter with the //! [`LookupSpan`] trait, like so: //! //! ```rust //! use tracing_subscriber::{registry, Layer}; //! use tracing_core::Subscriber; //! //! pub struct MyLayer { //! // ... //! } //! //! impl<S> Layer<S> for MyLayer //! where //! S: Subscriber + for<'a> registry::LookupSpan<'a>, //! { //! // ... //! } //! ``` //! When this bound is added, the `Layer` implementation will be guaranteed //! access to the [`Context`][ctx] methods, such as [`Context::span`][lookup], that //! require the root subscriber to be a registry. //! //! [`Layer`]: crate::layer::Layer //! [`Subscriber`]: tracing_core::Subscriber //! [ctx]: crate::layer::Context //! [lookup]: crate::layer::Context::span() use tracing_core::{field::FieldSet, span::Id, Metadata};
feature! { #![feature = "std"] /// A module containing a type map of span extensions. mod extensions; pubuse extensions::{Extensions, ExtensionsMut};
/// Provides access to stored span data. /// /// Subscribers which store span data and associate it with span IDs should /// implement this trait; if they do, any [`Layer`]s wrapping them can look up /// metadata via the [`Context`] type's [`span()`] method. /// /// [`Layer`]: super::layer::Layer /// [`Context`]: super::layer::Context /// [`span()`]: super::layer::Context::span pubtrait LookupSpan<'a> { /// The type of span data stored in this registry. type Data: SpanData<'a>;
/// Returns the [`SpanData`] for a given `Id`, if it exists. /// /// <pre class="ignore" style="white-space:normal;font:inherit;"> /// <strong>Note</strong>: users of the <code>LookupSpan</code> trait should /// typically call the <a href="#method.span"><code>span</code></a> method rather /// than this method. The <code>span</code> method is implemented by /// <em>calling</em> <code>span_data</code>, but returns a reference which is /// capable of performing more sophisiticated queries. /// </pre> /// fn span_data(&'a self, id: &Id) -> Option<Self::Data>;
/// Returns a [`SpanRef`] for the span with the given `Id`, if it exists. /// /// A `SpanRef` is similar to [`SpanData`], but it allows performing /// additional lookups against the registryr that stores the wrapped data. /// /// In general, _users_ of the `LookupSpan` trait should use this method /// rather than the [`span_data`] method; while _implementors_ of this trait /// should only implement `span_data`. /// /// [`span_data`]: LookupSpan::span_data() fn span(&'a self, id: &Id) -> Option<SpanRef<'a, Self>> where Self: Sized,
{ let data = self.span_data(id)?;
Some(SpanRef {
registry: self,
data, #[cfg(feature = "registry")]
filter: FilterId::none(),
})
}
/// Registers a [`Filter`] for [per-layer filtering] with this /// [`Subscriber`]. /// /// The [`Filter`] can then use the returned [`FilterId`] to /// [check if it previously enabled a span][check]. /// /// # Panics /// /// If this `Subscriber` does not support [per-layer filtering]. /// /// [`Filter`]: crate::layer::Filter /// [per-layer filtering]: crate::layer::Layer#per-layer-filtering /// [`Subscriber`]: tracing_core::Subscriber /// [`FilterId`]: crate::filter::FilterId /// [check]: SpanData::is_enabled_for #[cfg(feature = "registry")] #[cfg_attr(docsrs, doc(cfg(feature = "registry")))] fn register_filter(&mutself) -> FilterId {
panic!( "{} does not currently support filters",
std::any::type_name::<Self>()
)
}
}
/// A stored representation of data associated with a span. pubtrait SpanData<'a> { /// Returns this span's ID. fn id(&self) -> Id;
/// Returns a reference to the span's `Metadata`. fn metadata(&self) -> &'static Metadata<'static>;
/// Returns a reference to the ID fn parent(&self) -> Option<&Id>;
/// Returns a reference to this span's `Extensions`. /// /// The extensions may be used by `Layer`s to store additional data /// describing the span. #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] fn extensions(&self) -> Extensions<'_>;
/// Returns a mutable reference to this span's `Extensions`. /// /// The extensions may be used by `Layer`s to store additional data /// describing the span. #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] fn extensions_mut(&self) -> ExtensionsMut<'_>;
/// Returns `true` if this span is enabled for the [per-layer filter][plf] /// corresponding to the provided [`FilterId`]. /// /// ## Default Implementation /// /// By default, this method assumes that the [`LookupSpan`] implementation /// does not support [per-layer filtering][plf], and always returns `true`. /// /// [plf]: crate::layer::Layer#per-layer-filtering /// [`FilterId`]: crate::filter::FilterId #[cfg(feature = "registry")] #[cfg_attr(docsrs, doc(cfg(feature = "registry")))] fn is_enabled_for(&self, filter: FilterId) -> bool { let _ = filter; true
}
}
/// A reference to [span data] and the associated [registry]. /// /// This type implements all the same methods as [`SpanData`], and provides /// additional methods for querying the registry based on values from the span. /// /// [registry]: LookupSpan #[derive(Debug)] pubstruct SpanRef<'a, R: LookupSpan<'a>> {
registry: &'a R,
data: R::Data,
#[cfg(feature = "registry")]
filter: FilterId,
}
/// An iterator over the parents of a span, ordered from leaf to root. /// /// This is returned by the [`SpanRef::scope`] method. #[derive(Debug)] pubstruct Scope<'a, R> {
registry: &'a R,
next: Option<Id>,
#[cfg(not(feature = "smallvec"))] use alloc::vec::{self, Vec};
use core::{fmt,iter};
/// An iterator over the parents of a span, ordered from root to leaf. /// /// This is returned by the [`Scope::from_root`] method. pubstruct ScopeFromRoot<'a, R> where
R: LookupSpan<'a>,
{ #[cfg(feature = "smallvec")]
spans: iter::Rev<smallvec::IntoIter<SpanRefVecArray<'a, R>>>, #[cfg(not(feature = "smallvec"))]
spans: iter::Rev<vec::IntoIter<SpanRef<'a, R>>>,
}
#[cfg(feature = "smallvec")] type SpanRefVecArray<'span, L> = [SpanRef<'span, L>; 16];
impl<'a, R> Scope<'a, R> where
R: LookupSpan<'a>,
{ /// Flips the order of the iterator, so that it is ordered from root to leaf. /// /// The iterator will first return the root span, then that span's immediate child, /// and so on until it finally returns the span that [`SpanRef::scope`] was called on. /// /// If any items were consumed from the [`Scope`] before calling this method then they /// will *not* be returned from the [`ScopeFromRoot`]. /// /// **Note**: this will allocate if there are many spans remaining, or if the /// "smallvec" feature flag is not enabled. #[allow(clippy::wrong_self_convention)] pubfn from_root(self) -> ScopeFromRoot<'a, R> { #[cfg(feature = "smallvec")] type Buf<T> = smallvec::SmallVec<T>; #[cfg(not(feature = "smallvec"))] type Buf<T> = Vec<T>;
ScopeFromRoot {
spans: self.collect::<Buf<_>>().into_iter().rev(),
}
}
}
impl<'a, R> Iterator for ScopeFromRoot<'a, R> where
R: LookupSpan<'a>,
{ type Item = SpanRef<'a, R>;
// If the `Scope` is filtered, check if the current span is enabled // by the selected filter ID.
#[cfg(all(feature = "registry", feature = "std"))]
{ if !curr.is_enabled_for(self.filter) { // The current span in the chain is disabled for this // filter. Try its parent. continue;
}
}
return Some(curr);
}
}
}
impl<'a, R> SpanRef<'a, R> where
R: LookupSpan<'a>,
{ /// Returns this span's ID. pubfn id(&self) -> Id { self.data.id()
}
/// Returns a static reference to the span's metadata. pubfn metadata(&self) -> &'static Metadata<'static> { self.data.metadata()
}
/// Returns a list of [fields] defined by the span. /// /// [fields]: tracing_core::field pubfn fields(&self) -> &FieldSet { self.data.metadata().fields()
}
/// Returns a `SpanRef` describing this span's parent, or `None` if this /// span is the root of its trace tree. pubfn parent(&self) -> Option<Self> { let id = self.data.parent()?; let data = self.registry.span_data(id)?;
#[cfg(all(feature = "registry", feature = "std"))]
{ // move these into mut bindings if the registry feature is enabled, // since they may be mutated in the loop. letmut data = data; loop { // Is this parent enabled by our filter? if data.is_enabled_for(self.filter) { return Some(Self {
registry: self.registry,
filter: self.filter,
data,
});
}
// It's not enabled. If the disabled span has a parent, try that! let id = data.parent()?;
data = self.registry.span_data(id)?;
}
}
/// Returns a reference to this span's `Extensions`. /// /// The extensions may be used by `Layer`s to store additional data /// describing the span. #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pubfn extensions(&self) -> Extensions<'_> { self.data.extensions()
}
/// Returns a mutable reference to this span's `Extensions`. /// /// The extensions may be used by `Layer`s to store additional data /// describing the span. #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pubfn extensions_mut(&self) -> ExtensionsMut<'_> { self.data.extensions_mut()
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.