diff --git a/tracing-subscriber/Cargo.toml b/tracing-subscriber/Cargo.toml index 49ebb387..ff859126 100644 --- a/tracing-subscriber/Cargo.toml +++ b/tracing-subscriber/Cargo.toml @@ -24,6 +24,7 @@ default = ["env-filter", "smallvec", "fmt", "ansi", "chrono", "tracing-log"] env-filter = ["matchers", "regex", "lazy_static"] fmt = ["owning_ref"] ansi = ["fmt", "ansi_term"] +registry_unstable = [] # Alias for `env-filter`; renamed in version 0.1.2, and will be removed in 0.2. filter = ["env-filter"] @@ -56,6 +57,9 @@ criterion = { version = "0.3", default_features = false } azure-devops = { project = "tracing/tracing", pipeline = "tokio-rs.tracing", build = "1" } maintenance = { status = "experimental" } +[package.metadata.docs.rs] +all-features = true + [[bench]] name = "filter" harness = false diff --git a/tracing-subscriber/src/fmt/mod.rs b/tracing-subscriber/src/fmt/mod.rs index 8975411c..5f84487e 100644 --- a/tracing-subscriber/src/fmt/mod.rs +++ b/tracing-subscriber/src/fmt/mod.rs @@ -271,7 +271,19 @@ where } } +#[cfg(feature = "registry_unstable")] +impl crate::registry::LookupMetadata for Subscriber +where + layer::Layered>: crate::registry::LookupMetadata, +{ + #[inline] + fn metadata(&self, id: &span::Id) -> Option<&'static Metadata<'static>> { + self.inner.metadata(id) + } +} + // === impl Formatter === + impl Formatter where N: for<'writer> FormatFields<'writer>, @@ -378,6 +390,13 @@ where } } +#[cfg(feature = "registry_unstable")] +impl crate::registry::LookupMetadata for Formatter { + fn metadata(&self, id: &span::Id) -> Option<&'static Metadata<'static>> { + self.spans.get(&id).map(|span| span.metadata()) + } +} + // ===== impl Builder ===== impl Default for Builder { @@ -933,4 +952,11 @@ mod test { assert!(dispatch.downcast_ref::().is_some()); assert!(dispatch.downcast_ref::().is_some()) } + + #[test] + #[cfg(feature = "registry_unstable")] + fn is_lookup_meta() { + fn assert_lookup_meta(_: T) {} + assert_lookup_meta(Subscriber::builder().finish()) + } } diff --git a/tracing-subscriber/src/layer.rs b/tracing-subscriber/src/layer.rs index 73b13af6..66109a39 100644 --- a/tracing-subscriber/src/layer.rs +++ b/tracing-subscriber/src/layer.rs @@ -6,6 +6,8 @@ use tracing_core::{ Event, }; +#[cfg(feature = "registry_unstable")] +use crate::registry::LookupMetadata; use std::{any::TypeId, marker::PhantomData}; /// A composable handler for `tracing` events. @@ -605,6 +607,16 @@ where } } +#[cfg(feature = "registry_unstable")] +impl LookupMetadata for Layered +where + S: Subscriber + LookupMetadata, +{ + fn metadata(&self, span: &span::Id) -> Option<&'static Metadata<'static>> { + self.inner.metadata(span) + } +} + impl Layered where S: Subscriber, @@ -678,6 +690,42 @@ impl<'a, S: Subscriber> Context<'a, S> { subscriber.event(event); } } + + /// Returns metadata for tne span with the given `id`, if it exists. + /// + /// If this returns `None`, then no span exists for that ID (either it has + /// closed or the ID is invalid). + /// + /// **Note**: This requires the wrapped subscriber to implement the + /// [`LookupMetadata`] trait. `Layer` implementations that wish to use this + /// function can bound their `Subscriber` type parameter with + /// ```rust,ignore + /// where S: Subscriber + LookupMetadata, + /// ``` + /// or similar. + /// + /// [`LookupMetadata`]: ../registry/trait.LookupMetadata.html + #[inline] + #[cfg(feature = "registry_unstable")] + pub fn metadata(&self, id: &span::Id) -> Option<&'static Metadata<'static>> + where + S: LookupMetadata, + { + self.subscriber.as_ref()?.metadata(id) + } + + /// Returns `true` if an active span exists for the given `Id`. + #[inline] + #[cfg(feature = "registry_unstable")] + pub fn exists(&self, id: &span::Id) -> bool + where + S: LookupMetadata, + { + self.subscriber + .as_ref() + .map(|s| s.exists(id)) + .unwrap_or(false) + } } impl<'a, S> Context<'a, S> { diff --git a/tracing-subscriber/src/lib.rs b/tracing-subscriber/src/lib.rs index bb1d3e3b..ec3b5c97 100644 --- a/tracing-subscriber/src/lib.rs +++ b/tracing-subscriber/src/lib.rs @@ -25,7 +25,9 @@ //! - `fmt`: Enables the [`fmt`] module, which provides a subscriber //! implementation for printing formatted representations of trace events. //! Enabled by default. -//! - `ansi`: Enables `fmt` support for ANSI terminal colors. Enabled by default. +//! - `ansi`: Enables `fmt` support for ANSI terminal colors. Enabled by +//! default. +//! - `registry_unstable`: enables the experimental [`registry`] module. //! //! ### Optional Dependencies //! @@ -47,6 +49,7 @@ //! [`chrono`]: https://crates.io/crates/chrono //! [`env_logger` crate]: https://crates.io/crates/env_logger //! [`parking_lot`]: https://crates.io/crates/parking_lot +//! [`registry`]: registry/index.html #![doc(html_root_url = "https://docs.rs/tracing-subscriber/0.1.5")] #![warn( missing_debug_implementations, @@ -105,6 +108,8 @@ pub mod filter; pub mod fmt; pub mod layer; pub mod prelude; +#[cfg(feature = "registry_unstable")] +pub mod registry; pub mod reload; pub(crate) mod sync; pub(crate) mod thread; diff --git a/tracing-subscriber/src/registry/mod.rs b/tracing-subscriber/src/registry/mod.rs new file mode 100644 index 00000000..e12808d7 --- /dev/null +++ b/tracing-subscriber/src/registry/mod.rs @@ -0,0 +1,47 @@ +//! **EXPERIMENTAL**: Storage for span data shared by multiple [`Layer`]s. +//! +//! This module is experimental. Although potential breaking changes will be +//! avoided when possible, we reserve the right to make breaking changes to this +//! module until it is no longer experimental. +//! +//! Add the `registry_unstable` feature to your `Cargo.toml` to enable +//! this module: +//! +//! ```toml +//! [dependencies.tracing-subscriber] +//! features = ["registry_unstable"] +//! ``` +//! +//! [`Layer`]: ../layer/struct.Layer.html +use tracing_core::{span::Id, Metadata}; +/// Provides access to stored span metadata. +/// +/// Subscribers which store span metadata 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 [`metadata()`] method. +/// +/// [`Layer`]: ../layer/struct.Layer.html +/// [`Context`]: ../layer/struct.Context.html +/// [`metadata()`]: ../layer/struct.Context.html#method.metadata +pub trait LookupMetadata { + /// Returns metadata for tne span with the given `id`, if it exists. + /// + /// If no span exists for the provided ID (e.g. the span has closed and been + /// removed from the registry, or the ID is invalid), this should return `None`. + fn metadata(&self, id: &Id) -> Option<&'static Metadata<'static>>; + + /// Returns `true` if a span with the given `id` exists, false otherwise. + /// + /// **Note**: The default implementation of this method is simply: + ///```rust,ignore + /// fn exists(&self, id: &span::Id) -> bool { + /// self.metadata(id).is_some() + /// } + ///``` + /// If the subscriber has a faster way of determining whether a span exists + /// for a given ID (e.g., if the ID is greater than the current value of an + /// increasing ID counter, etc), this method may be overridden as an optimization. + fn exists(&self, id: &Id) -> bool { + self.metadata(id).is_some() + } +}