From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/tracing-subscriber/src/registry/mod.rs | 600 ++++++++++++++++++++++++++ 1 file changed, 600 insertions(+) create mode 100644 vendor/tracing-subscriber/src/registry/mod.rs (limited to 'vendor/tracing-subscriber/src/registry/mod.rs') 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 Layer for FooLayer {} +//! # impl Layer 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 Layer 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. + /// + ///
+    /// Note: users of the LookupSpan trait should
+    /// typically call the span method rather
+    /// than this method. The span method is implemented by
+    /// calling span_data, but returns a reference which is
+    /// capable of performing more sophisiticated queries.
+    /// 
+ /// + fn span_data(&'a self, id: &Id) -> Option; + + /// 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> + 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::() + ) + } +} + +/// 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, + + #[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>>, + #[cfg(not(feature = "smallvec"))] + spans: iter::Rev>>, + } + + #[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 = smallvec::SmallVec; + #[cfg(not(feature = "smallvec"))] + type Buf = Vec; + ScopeFromRoot { + spans: self.collect::>().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.spans.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + 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 { + 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 { + 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 Layer for PrintingLayer + /// where + /// S: Subscriber + for<'lookup> LookupSpan<'lookup>, + /// { + /// fn on_enter(&self, id: &span::Id, ctx: Context) { + /// let span = ctx.span(id).unwrap(); + /// let scope = span.scope().map(|span| span.name()).collect::>(); + /// 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 Layer for PrintingLayer + /// where + /// S: Subscriber + for<'lookup> LookupSpan<'lookup>, + /// { + /// fn on_enter(&self, id: &span::Id, ctx: Context) { + /// let span = ctx.span(id).unwrap(); + /// let scope = span.scope().from_root().map(|span| span.name()).collect::>(); + /// 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 { + 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>>, + } + + impl Layer 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::>(); + *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>>, + } + + impl Layer 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::>(); + *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"] + ); + } +} -- cgit v1.2.3