summaryrefslogtreecommitdiffstats
path: root/vendor/tracing-subscriber/src/registry/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/tracing-subscriber/src/registry/mod.rs')
-rw-r--r--vendor/tracing-subscriber/src/registry/mod.rs600
1 files changed, 600 insertions, 0 deletions
diff --git a/vendor/tracing-subscriber/src/registry/mod.rs b/vendor/tracing-subscriber/src/registry/mod.rs
new file mode 100644
index 000000000..38af53e8a
--- /dev/null
+++ b/vendor/tracing-subscriber/src/registry/mod.rs
@@ -0,0 +1,600 @@
+//! 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;
+ pub use extensions::{Extensions, ExtensionsMut};
+
+}
+
+feature! {
+ #![all(feature = "registry", feature = "std")]
+
+ mod sharded;
+ mod stack;
+
+ pub use sharded::Data;
+ pub use sharded::Registry;
+
+ use crate::filter::FilterId;
+}
+
+/// 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
+pub trait 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<'_, 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(&mut self) -> FilterId {
+ panic!(
+ "{} does not currently support filters",
+ std::any::type_name::<Self>()
+ )
+ }
+}
+
+/// A stored representation of data associated with a span.
+pub trait 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`][span data], and
+/// provides additional methods for querying the registry based on values from
+/// the span.
+///
+/// [span data]: SpanData
+/// [registry]: LookupSpan
+#[derive(Debug)]
+pub struct 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)]
+pub struct Scope<'a, R> {
+ registry: &'a R,
+ next: Option<Id>,
+
+ #[cfg(all(feature = "registry", feature = "std"))]
+ filter: FilterId,
+}
+
+feature! {
+ #![any(feature = "alloc", feature = "std")]
+
+ #[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.
+ pub struct 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)]
+ pub fn 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>;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ self.spans.next()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.spans.size_hint()
+ }
+ }
+
+ impl<'a, R> fmt::Debug for ScopeFromRoot<'a, R>
+ where
+ R: LookupSpan<'a>,
+ {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.pad("ScopeFromRoot { .. }")
+ }
+ }
+}
+
+impl<'a, R> Iterator for Scope<'a, R>
+where
+ R: LookupSpan<'a>,
+{
+ type Item = SpanRef<'a, R>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ loop {
+ let curr = self.registry.span(self.next.as_ref()?)?;
+
+ #[cfg(all(feature = "registry", feature = "std"))]
+ let curr = curr.with_filter(self.filter);
+ self.next = curr.data.parent().cloned();
+
+ // 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.
+ pub fn id(&self) -> Id {
+ self.data.id()
+ }
+
+ /// Returns a static reference to the span's metadata.
+ pub fn metadata(&self) -> &'static Metadata<'static> {
+ self.data.metadata()
+ }
+
+ /// Returns the span's name,
+ pub fn name(&self) -> &'static str {
+ self.data.metadata().name()
+ }
+
+ /// Returns a list of [fields] defined by the span.
+ ///
+ /// [fields]: tracing_core::field
+ pub fn 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.
+ pub fn 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.
+ let mut 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)?;
+ }
+ }
+
+ #[cfg(not(all(feature = "registry", feature = "std")))]
+ Some(Self {
+ registry: self.registry,
+ data,
+ })
+ }
+
+ /// Returns an iterator over all parents of this span, starting with this span,
+ /// ordered from leaf to root.
+ ///
+ /// The iterator will first return the span, then the span's immediate parent,
+ /// followed by that span's parent, and so on, until it reaches a root span.
+ ///
+ /// ```rust
+ /// use tracing::{span, Subscriber};
+ /// use tracing_subscriber::{
+ /// layer::{Context, Layer},
+ /// prelude::*,
+ /// registry::LookupSpan,
+ /// };
+ ///
+ /// struct PrintingLayer;
+ /// impl<S> Layer<S> for PrintingLayer
+ /// where
+ /// S: Subscriber + for<'lookup> LookupSpan<'lookup>,
+ /// {
+ /// fn on_enter(&self, id: &span::Id, ctx: Context<S>) {
+ /// let span = ctx.span(id).unwrap();
+ /// let scope = span.scope().map(|span| span.name()).collect::<Vec<_>>();
+ /// println!("Entering span: {:?}", scope);
+ /// }
+ /// }
+ ///
+ /// tracing::subscriber::with_default(tracing_subscriber::registry().with(PrintingLayer), || {
+ /// let _root = tracing::info_span!("root").entered();
+ /// // Prints: Entering span: ["root"]
+ /// let _child = tracing::info_span!("child").entered();
+ /// // Prints: Entering span: ["child", "root"]
+ /// let _leaf = tracing::info_span!("leaf").entered();
+ /// // Prints: Entering span: ["leaf", "child", "root"]
+ /// });
+ /// ```
+ ///
+ /// If the opposite order (from the root to this span) is desired, calling [`Scope::from_root`] on
+ /// the returned iterator reverses the order.
+ ///
+ /// ```rust
+ /// # use tracing::{span, Subscriber};
+ /// # use tracing_subscriber::{
+ /// # layer::{Context, Layer},
+ /// # prelude::*,
+ /// # registry::LookupSpan,
+ /// # };
+ /// # struct PrintingLayer;
+ /// impl<S> Layer<S> for PrintingLayer
+ /// where
+ /// S: Subscriber + for<'lookup> LookupSpan<'lookup>,
+ /// {
+ /// fn on_enter(&self, id: &span::Id, ctx: Context<S>) {
+ /// let span = ctx.span(id).unwrap();
+ /// let scope = span.scope().from_root().map(|span| span.name()).collect::<Vec<_>>();
+ /// println!("Entering span: {:?}", scope);
+ /// }
+ /// }
+ ///
+ /// tracing::subscriber::with_default(tracing_subscriber::registry().with(PrintingLayer), || {
+ /// let _root = tracing::info_span!("root").entered();
+ /// // Prints: Entering span: ["root"]
+ /// let _child = tracing::info_span!("child").entered();
+ /// // Prints: Entering span: ["root", "child"]
+ /// let _leaf = tracing::info_span!("leaf").entered();
+ /// // Prints: Entering span: ["root", "child", "leaf"]
+ /// });
+ /// ```
+ pub fn scope(&self) -> Scope<'a, R> {
+ Scope {
+ registry: self.registry,
+ next: Some(self.id()),
+
+ #[cfg(feature = "registry")]
+ filter: self.filter,
+ }
+ }
+
+ /// 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")))]
+ pub fn 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")))]
+ pub fn extensions_mut(&self) -> ExtensionsMut<'_> {
+ self.data.extensions_mut()
+ }
+
+ #[cfg(all(feature = "registry", feature = "std"))]
+ pub(crate) fn try_with_filter(self, filter: FilterId) -> Option<Self> {
+ if self.is_enabled_for(filter) {
+ return Some(self.with_filter(filter));
+ }
+
+ None
+ }
+
+ #[inline]
+ #[cfg(all(feature = "registry", feature = "std"))]
+ pub(crate) fn is_enabled_for(&self, filter: FilterId) -> bool {
+ self.data.is_enabled_for(filter)
+ }
+
+ #[inline]
+ #[cfg(all(feature = "registry", feature = "std"))]
+ fn with_filter(self, filter: FilterId) -> Self {
+ Self { filter, ..self }
+ }
+}
+
+#[cfg(all(test, feature = "registry", feature = "std"))]
+mod tests {
+ use crate::{
+ layer::{Context, Layer},
+ prelude::*,
+ registry::LookupSpan,
+ };
+ use std::sync::{Arc, Mutex};
+ use tracing::{span, Subscriber};
+
+ #[test]
+ fn spanref_scope_iteration_order() {
+ let last_entered_scope = Arc::new(Mutex::new(Vec::new()));
+
+ #[derive(Default)]
+ struct PrintingLayer {
+ last_entered_scope: Arc<Mutex<Vec<&'static str>>>,
+ }
+
+ impl<S> Layer<S> for PrintingLayer
+ where
+ S: Subscriber + for<'lookup> LookupSpan<'lookup>,
+ {
+ fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
+ let span = ctx.span(id).unwrap();
+ let scope = span.scope().map(|span| span.name()).collect::<Vec<_>>();
+ *self.last_entered_scope.lock().unwrap() = scope;
+ }
+ }
+
+ let _guard = tracing::subscriber::set_default(crate::registry().with(PrintingLayer {
+ last_entered_scope: last_entered_scope.clone(),
+ }));
+
+ let _root = tracing::info_span!("root").entered();
+ assert_eq!(&*last_entered_scope.lock().unwrap(), &["root"]);
+ let _child = tracing::info_span!("child").entered();
+ assert_eq!(&*last_entered_scope.lock().unwrap(), &["child", "root"]);
+ let _leaf = tracing::info_span!("leaf").entered();
+ assert_eq!(
+ &*last_entered_scope.lock().unwrap(),
+ &["leaf", "child", "root"]
+ );
+ }
+
+ #[test]
+ fn spanref_scope_fromroot_iteration_order() {
+ let last_entered_scope = Arc::new(Mutex::new(Vec::new()));
+
+ #[derive(Default)]
+ struct PrintingLayer {
+ last_entered_scope: Arc<Mutex<Vec<&'static str>>>,
+ }
+
+ impl<S> Layer<S> for PrintingLayer
+ where
+ S: Subscriber + for<'lookup> LookupSpan<'lookup>,
+ {
+ fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
+ let span = ctx.span(id).unwrap();
+ let scope = span
+ .scope()
+ .from_root()
+ .map(|span| span.name())
+ .collect::<Vec<_>>();
+ *self.last_entered_scope.lock().unwrap() = scope;
+ }
+ }
+
+ let _guard = tracing::subscriber::set_default(crate::registry().with(PrintingLayer {
+ last_entered_scope: last_entered_scope.clone(),
+ }));
+
+ let _root = tracing::info_span!("root").entered();
+ assert_eq!(&*last_entered_scope.lock().unwrap(), &["root"]);
+ let _child = tracing::info_span!("child").entered();
+ assert_eq!(&*last_entered_scope.lock().unwrap(), &["root", "child",]);
+ let _leaf = tracing::info_span!("leaf").entered();
+ assert_eq!(
+ &*last_entered_scope.lock().unwrap(),
+ &["root", "child", "leaf"]
+ );
+ }
+}