diff options
Diffstat (limited to '')
-rw-r--r-- | vendor/tracing-core/src/callsite.rs | 10 | ||||
-rw-r--r-- | vendor/tracing-core/src/dispatcher.rs | 128 | ||||
-rw-r--r-- | vendor/tracing-core/src/field.rs | 44 | ||||
-rw-r--r-- | vendor/tracing-core/src/metadata.rs | 89 | ||||
-rw-r--r-- | vendor/tracing-core/src/subscriber.rs | 27 |
5 files changed, 268 insertions, 30 deletions
diff --git a/vendor/tracing-core/src/callsite.rs b/vendor/tracing-core/src/callsite.rs index d0fe1a3d6..f88713236 100644 --- a/vendor/tracing-core/src/callsite.rs +++ b/vendor/tracing-core/src/callsite.rs @@ -137,6 +137,15 @@ pub trait Callsite: Sync { /// Returns the [metadata] associated with the callsite. /// + /// <div class="example-wrap" style="display:inline-block"> + /// <pre class="ignore" style="white-space:normal;font:inherit;"> + /// + /// **Note:** Implementations of this method should not produce [`Metadata`] + /// that share the same callsite [`Identifier`] but otherwise differ in any + /// way (e.g., have different `name`s). + /// + /// </pre></div> + /// /// [metadata]: super::metadata::Metadata fn metadata(&self) -> &Metadata<'_>; @@ -478,6 +487,7 @@ impl Callsites { pub(crate) fn register_dispatch(dispatch: &Dispatch) { let dispatchers = DISPATCHERS.register_dispatch(dispatch); + dispatch.subscriber().on_register_dispatch(dispatch); CALLSITES.rebuild_interest(dispatchers); } diff --git a/vendor/tracing-core/src/dispatcher.rs b/vendor/tracing-core/src/dispatcher.rs index 041722c36..36b3cfd85 100644 --- a/vendor/tracing-core/src/dispatcher.rs +++ b/vendor/tracing-core/src/dispatcher.rs @@ -134,7 +134,7 @@ use crate::stdlib::{ fmt, sync::{ atomic::{AtomicBool, AtomicUsize, Ordering}, - Arc, + Arc, Weak, }, }; @@ -142,16 +142,50 @@ use crate::stdlib::{ use crate::stdlib::{ cell::{Cell, RefCell, RefMut}, error, - sync::Weak, }; +#[cfg(feature = "alloc")] +use alloc::sync::{Arc, Weak}; + +#[cfg(feature = "alloc")] +use core::ops::Deref; + /// `Dispatch` trace data to a [`Subscriber`]. -/// #[derive(Clone)] pub struct Dispatch { subscriber: Arc<dyn Subscriber + Send + Sync>, } +/// `WeakDispatch` is a version of [`Dispatch`] that holds a non-owning reference +/// to a [`Subscriber`]. +/// +/// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`], +/// which returns an `Option<Dispatch>`. If all [`Dispatch`] clones that point +/// at the `Subscriber` have been dropped, [`WeakDispatch::upgrade`] will return +/// `None`. Otherwise, it will return `Some(Dispatch)`. +/// +/// A `WeakDispatch` may be created from a [`Dispatch`] by calling the +/// [`Dispatch::downgrade`] method. The primary use for creating a +/// [`WeakDispatch`] is to allow a Subscriber` to hold a cyclical reference to +/// itself without creating a memory leak. See [here] for details. +/// +/// This type is analogous to the [`std::sync::Weak`] type, but for a +/// [`Dispatch`] rather than an [`Arc`]. +/// +/// [`Arc`]: std::sync::Arc +/// [here]: Subscriber#avoiding-memory-leaks +#[derive(Clone)] +pub struct WeakDispatch { + subscriber: Weak<dyn Subscriber + Send + Sync>, +} + +#[cfg(feature = "alloc")] +#[derive(Clone)] +enum Kind<T> { + Global(&'static (dyn Collect + Send + Sync)), + Scoped(T), +} + #[cfg(feature = "std")] thread_local! { static CURRENT_STATE: State = State { @@ -293,14 +327,21 @@ pub fn has_been_set() -> bool { } /// Returned if setting the global dispatcher fails. -#[derive(Debug)] pub struct SetGlobalDefaultError { _no_construct: (), } +impl fmt::Debug for SetGlobalDefaultError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("SetGlobalDefaultError") + .field(&Self::MESSAGE) + .finish() + } +} + impl fmt::Display for SetGlobalDefaultError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("a global default trace dispatcher has already been set") + f.pad(Self::MESSAGE) } } @@ -308,6 +349,10 @@ impl fmt::Display for SetGlobalDefaultError { #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl error::Error for SetGlobalDefaultError {} +impl SetGlobalDefaultError { + const MESSAGE: &'static str = "a global default trace dispatcher has already been set"; +} + /// Executes a closure with a reference to this thread's current [dispatcher]. /// /// Note that calls to `get_default` should not be nested; if this function is @@ -419,8 +464,34 @@ impl Dispatch { Registrar(Arc::downgrade(&self.subscriber)) } - /// Registers a new callsite with this subscriber, returning whether or not - /// the subscriber is interested in being notified about the callsite. + /// Creates a [`WeakDispatch`] from this `Dispatch`. + /// + /// A [`WeakDispatch`] is similar to a [`Dispatch`], but it does not prevent + /// the underlying [`Subscriber`] from being dropped. Instead, it only permits + /// access while other references to the `Subscriber` exist. This is equivalent + /// to the standard library's [`Arc::downgrade`] method, but for `Dispatch` + /// rather than `Arc`. + /// + /// The primary use for creating a [`WeakDispatch`] is to allow a `Subscriber` + /// to hold a cyclical reference to itself without creating a memory leak. + /// See [here] for details. + /// + /// [`Arc::downgrade`]: std::sync::Arc::downgrade + /// [here]: Subscriber#avoiding-memory-leaks + pub fn downgrade(&self) -> WeakDispatch { + WeakDispatch { + subscriber: Arc::downgrade(&self.subscriber), + } + } + + #[inline(always)] + #[cfg(not(feature = "alloc"))] + pub(crate) fn subscriber(&self) -> &(dyn Subscriber + Send + Sync) { + &self.subscriber + } + + /// Registers a new callsite with this collector, returning whether or not + /// the collector is interested in being notified about the callsite. /// /// This calls the [`register_callsite`] function on the [`Subscriber`] /// that this `Dispatch` forwards to. @@ -620,14 +691,14 @@ impl Dispatch { /// `T`. #[inline] pub fn is<T: Any>(&self) -> bool { - <dyn Subscriber>::is::<T>(&*self.subscriber) + <dyn Subscriber>::is::<T>(&self.subscriber) } /// Returns some reference to the `Subscriber` this `Dispatch` forwards to /// if it is of type `T`, or `None` if it isn't. #[inline] pub fn downcast_ref<T: Any>(&self) -> Option<&T> { - <dyn Subscriber>::downcast_ref(&*self.subscriber) + <dyn Subscriber>::downcast_ref(&self.subscriber) } } @@ -656,6 +727,45 @@ where } } +// === impl WeakDispatch === + +impl WeakDispatch { + /// Attempts to upgrade this `WeakDispatch` to a [`Dispatch`]. + /// + /// Returns `None` if the referenced `Dispatch` has already been dropped. + /// + /// ## Examples + /// + /// ``` + /// # use tracing_core::subscriber::NoSubscriber; + /// # use tracing_core::dispatcher::Dispatch; + /// let strong = Dispatch::new(NoSubscriber::default()); + /// let weak = strong.downgrade(); + /// + /// // The strong here keeps it alive, so we can still access the object. + /// assert!(weak.upgrade().is_some()); + /// + /// drop(strong); // But not any more. + /// assert!(weak.upgrade().is_none()); + /// ``` + pub fn upgrade(&self) -> Option<Dispatch> { + self.subscriber + .upgrade() + .map(|subscriber| Dispatch { subscriber }) + } +} + +impl fmt::Debug for WeakDispatch { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut tuple = f.debug_tuple("WeakDispatch"); + match self.subscriber.upgrade() { + Some(subscriber) => tuple.field(&format_args!("Some({:p})", subscriber)), + None => tuple.field(&format_args!("None")), + }; + tuple.finish() + } +} + #[cfg(feature = "std")] impl Registrar { pub(crate) fn upgrade(&self) -> Option<Dispatch> { diff --git a/vendor/tracing-core/src/field.rs b/vendor/tracing-core/src/field.rs index c9869ce2c..e103c75a9 100644 --- a/vendor/tracing-core/src/field.rs +++ b/vendor/tracing-core/src/field.rs @@ -145,6 +145,16 @@ pub struct Field { pub struct Empty; /// Describes the fields present on a span. +/// +/// ## Equality +/// +/// In well-behaved applications, two `FieldSet`s [initialized] with equal +/// [callsite identifiers] will have identical fields. Consequently, in release +/// builds, [`FieldSet::eq`] *only* checks that its arguments have equal +/// callsites. However, the equality of field names is checked in debug builds. +/// +/// [initialized]: Self::new +/// [callsite identifiers]: callsite::Identifier pub struct FieldSet { /// The names of each field on the described span. names: &'static [&'static str], @@ -911,6 +921,40 @@ impl fmt::Display for FieldSet { } } +impl Eq for FieldSet {} + +impl PartialEq for FieldSet { + fn eq(&self, other: &Self) -> bool { + if core::ptr::eq(&self, &other) { + true + } else if cfg!(not(debug_assertions)) { + // In a well-behaving application, two `FieldSet`s can be assumed to + // be totally equal so long as they share the same callsite. + self.callsite == other.callsite + } else { + // However, when debug-assertions are enabled, do NOT assume that + // the application is well-behaving; check every the field names of + // each `FieldSet` for equality. + + // `FieldSet` is destructured here to ensure a compile-error if the + // fields of `FieldSet` change. + let Self { + names: lhs_names, + callsite: lhs_callsite, + } = self; + + let Self { + names: rhs_names, + callsite: rhs_callsite, + } = &other; + + // Check callsite equality first, as it is probably cheaper to do + // than str equality. + lhs_callsite == rhs_callsite && lhs_names == rhs_names + } + } +} + // ===== impl Iter ===== impl Iterator for Iter { diff --git a/vendor/tracing-core/src/metadata.rs b/vendor/tracing-core/src/metadata.rs index 47b9388a4..a154419a7 100644 --- a/vendor/tracing-core/src/metadata.rs +++ b/vendor/tracing-core/src/metadata.rs @@ -35,28 +35,25 @@ use crate::stdlib::{ /// _significantly_ lower than that of creating the actual span. Therefore, /// filtering is based on metadata, rather than on the constructed span. /// -/// <pre class="ignore" style="white-space:normal;font:inherit;"> -/// <strong>Note</strong>: Although instances of <code>Metadata</code> -/// cannot be compared directly, they provide a method -/// <a href="struct.Metadata.html#method.id"><code>id</code></a>, returning -/// an opaque <a href="../callsite/struct.Identifier.html">callsite -/// identifier</a>which uniquely identifies the callsite where the metadata -/// originated. This can be used to determine if two <code>Metadata</code> -/// correspond to the same callsite. -/// </pre> +/// ## Equality +/// +/// In well-behaved applications, two `Metadata` with equal +/// [callsite identifiers] will be equal in all other ways (i.e., have the same +/// `name`, `target`, etc.). Consequently, in release builds, [`Metadata::eq`] +/// *only* checks that its arguments have equal callsites. However, the equality +/// of `Metadata`'s other fields is checked in debug builds. /// /// [span]: super::span /// [event]: super::event -/// [name]: Metadata::name() -/// [target]: Metadata::target() -/// [fields]: Metadata::fields() -/// [verbosity level]: Metadata::level() -/// [file name]: Metadata::file() -/// [line number]: Metadata::line() -/// [module path]: Metadata::module_path() +/// [name]: Self::name +/// [target]: Self::target +/// [fields]: Self::fields +/// [verbosity level]: Self::level +/// [file name]: Self::file +/// [line number]: Self::line +/// [module path]: Self::module_path /// [`Subscriber`]: super::subscriber::Subscriber -/// [`id`]: Metadata::id -/// [callsite identifier]: super::callsite::Identifier +/// [callsite identifiers]: Self::callsite pub struct Metadata<'a> { /// The name of the span described by this metadata. name: &'static str, @@ -443,6 +440,62 @@ impl fmt::Debug for Kind { } } +impl<'a> Eq for Metadata<'a> {} + +impl<'a> PartialEq for Metadata<'a> { + #[inline] + fn eq(&self, other: &Self) -> bool { + if core::ptr::eq(&self, &other) { + true + } else if cfg!(not(debug_assertions)) { + // In a well-behaving application, two `Metadata` can be assumed to + // be totally equal so long as they share the same callsite. + self.callsite() == other.callsite() + } else { + // However, when debug-assertions are enabled, do not assume that + // the application is well-behaving; check every field of `Metadata` + // for equality. + + // `Metadata` is destructured here to ensure a compile-error if the + // fields of `Metadata` change. + let Metadata { + name: lhs_name, + target: lhs_target, + level: lhs_level, + module_path: lhs_module_path, + file: lhs_file, + line: lhs_line, + fields: lhs_fields, + kind: lhs_kind, + } = self; + + let Metadata { + name: rhs_name, + target: rhs_target, + level: rhs_level, + module_path: rhs_module_path, + file: rhs_file, + line: rhs_line, + fields: rhs_fields, + kind: rhs_kind, + } = &other; + + // The initial comparison of callsites is purely an optimization; + // it can be removed without affecting the overall semantics of the + // expression. + self.callsite() == other.callsite() + && lhs_name == rhs_name + && lhs_target == rhs_target + && lhs_level == rhs_level + && lhs_module_path == rhs_module_path + && lhs_file == rhs_file + && lhs_line == rhs_line + && lhs_fields == rhs_fields + && lhs_kind == rhs_kind + } + } +} + // ===== impl Level ===== impl Level { diff --git a/vendor/tracing-core/src/subscriber.rs b/vendor/tracing-core/src/subscriber.rs index a6f0834e2..e8f444119 100644 --- a/vendor/tracing-core/src/subscriber.rs +++ b/vendor/tracing-core/src/subscriber.rs @@ -1,5 +1,5 @@ -//! Subscribers collect and record trace data. -use crate::{span, Event, LevelFilter, Metadata}; +//! Collectors collect and record trace data. +use crate::{span, Dispatch, Event, LevelFilter, Metadata}; use crate::stdlib::{ any::{Any, TypeId}, @@ -81,7 +81,28 @@ use crate::stdlib::{ /// [`event`]: Subscriber::event /// [`event_enabled`]: Subscriber::event_enabled pub trait Subscriber: 'static { - // === Span registry methods ============================================== + /// Invoked when this subscriber becomes a [`Dispatch`]. + /// + /// ## Avoiding Memory Leaks + /// + /// `Subscriber`s should not store their own [`Dispatch`]. Because the + /// `Dispatch` owns the `Subscriber`, storing the `Dispatch` within the + /// `Subscriber` will create a reference count cycle, preventing the `Dispatch` + /// from ever being dropped. + /// + /// Instead, when it is necessary to store a cyclical reference to the + /// `Dispatch` within a `Subscriber`, use [`Dispatch::downgrade`] to convert a + /// `Dispatch` into a [`WeakDispatch`]. This type is analogous to + /// [`std::sync::Weak`], and does not create a reference count cycle. A + /// [`WeakDispatch`] can be stored within a `Subscriber` without causing a + /// memory leak, and can be [upgraded] into a `Dispatch` temporarily when + /// the `Dispatch` must be accessed by the `Subscriber`. + /// + /// [`WeakDispatch`]: crate::dispatcher::WeakDispatch + /// [upgraded]: crate::dispatcher::WeakDispatch::upgrade + fn on_register_dispatch(&self, subscriber: &Dispatch) { + let _ = subscriber; + } /// Registers a new [callsite] with this subscriber, returning whether or not /// the subscriber is interested in being notified about the callsite. |