RPM build fix (reverted CI changes which will need to be un-reverted or made conditional) and vendor Rust dependencies to make builds much faster in any CI system.
This commit is contained in:
618
zeroidc/vendor/tracing-core/src/callsite.rs
vendored
Normal file
618
zeroidc/vendor/tracing-core/src/callsite.rs
vendored
Normal file
@@ -0,0 +1,618 @@
|
||||
//! Callsites represent the source locations from which spans or events
|
||||
//! originate.
|
||||
//!
|
||||
//! # What Are Callsites?
|
||||
//!
|
||||
//! Every span or event in `tracing` is associated with a [`Callsite`]. A
|
||||
//! callsite is a small `static` value that is responsible for the following:
|
||||
//!
|
||||
//! * Storing the span or event's [`Metadata`],
|
||||
//! * Uniquely [identifying](Identifier) the span or event definition,
|
||||
//! * Caching the subscriber's [`Interest`][^1] in that span or event, to avoid
|
||||
//! re-evaluating filters,
|
||||
//! * Storing a [`Registration`] that allows the callsite to be part of a global
|
||||
//! list of all callsites in the program.
|
||||
//!
|
||||
//! # Registering Callsites
|
||||
//!
|
||||
//! When a span or event is recorded for the first time, its callsite
|
||||
//! [`register`]s itself with the global callsite registry. Registering a
|
||||
//! callsite calls the [`Subscriber::register_callsite`][`register_callsite`]
|
||||
//! method with that callsite's [`Metadata`] on every currently active
|
||||
//! subscriber. This serves two primary purposes: informing subscribers of the
|
||||
//! callsite's existence, and performing static filtering.
|
||||
//!
|
||||
//! ## Callsite Existence
|
||||
//!
|
||||
//! If a [`Subscriber`] implementation wishes to allocate storage for each
|
||||
//! unique span/event location in the program, or pre-compute some value
|
||||
//! that will be used to record that span or event in the future, it can
|
||||
//! do so in its [`register_callsite`] method.
|
||||
//!
|
||||
//! ## Performing Static Filtering
|
||||
//!
|
||||
//! The [`register_callsite`] method returns an [`Interest`] value,
|
||||
//! which indicates that the subscriber either [always] wishes to record
|
||||
//! that span or event, [sometimes] wishes to record it based on a
|
||||
//! dynamic filter evaluation, or [never] wishes to record it.
|
||||
//!
|
||||
//! When registering a new callsite, the [`Interest`]s returned by every
|
||||
//! currently active subscriber are combined, and the result is stored at
|
||||
//! each callsite. This way, when the span or event occurs in the
|
||||
//! future, the cached [`Interest`] value can be checked efficiently
|
||||
//! to determine if the span or event should be recorded, without
|
||||
//! needing to perform expensive filtering (i.e. calling the
|
||||
//! [`Subscriber::enabled`] method every time a span or event occurs).
|
||||
//!
|
||||
//! ### Rebuilding Cached Interest
|
||||
//!
|
||||
//! When a new [`Dispatch`] is created (i.e. a new subscriber becomes
|
||||
//! active), any previously cached [`Interest`] values are re-evaluated
|
||||
//! for all callsites in the program. This way, if the new subscriber
|
||||
//! will enable a callsite that was not previously enabled, the
|
||||
//! [`Interest`] in that callsite is updated. Similarly, when a
|
||||
//! subscriber is dropped, the interest cache is also re-evaluated, so
|
||||
//! that any callsites enabled only by that subscriber are disabled.
|
||||
//!
|
||||
//! In addition, the [`rebuild_interest_cache`] function in this module can be
|
||||
//! used to manually invalidate all cached interest and re-register those
|
||||
//! callsites. This function is useful in situations where a subscriber's
|
||||
//! interest can change, but it does so relatively infrequently. The subscriber
|
||||
//! may wish for its interest to be cached most of the time, and return
|
||||
//! [`Interest::always`][always] or [`Interest::never`][never] in its
|
||||
//! [`register_callsite`] method, so that its [`Subscriber::enabled`] method
|
||||
//! doesn't need to be evaluated every time a span or event is recorded.
|
||||
//! However, when the configuration changes, the subscriber can call
|
||||
//! [`rebuild_interest_cache`] to re-evaluate the entire interest cache with its
|
||||
//! new configuration. This is a relatively costly operation, but if the
|
||||
//! configuration changes infrequently, it may be more efficient than calling
|
||||
//! [`Subscriber::enabled`] frequently.
|
||||
//!
|
||||
//! # Implementing Callsites
|
||||
//!
|
||||
//! In most cases, instrumenting code using `tracing` should *not* require
|
||||
//! implementing the [`Callsite`] trait directly. When using the [`tracing`
|
||||
//! crate's macros][macros] or the [`#[instrument]` attribute][instrument], a
|
||||
//! `Callsite` is automatically generated.
|
||||
//!
|
||||
//! However, code which provides alternative forms of `tracing` instrumentation
|
||||
//! may need to interact with the callsite system directly. If
|
||||
//! instrumentation-side code needs to produce a `Callsite` to emit spans or
|
||||
//! events, the [`DefaultCallsite`] struct provided in this module is a
|
||||
//! ready-made `Callsite` implementation that is suitable for most uses. When
|
||||
//! possible, the use of `DefaultCallsite` should be preferred over implementing
|
||||
//! [`Callsite`] for user types, as `DefaultCallsite` may benefit from
|
||||
//! additional performance optimizations.
|
||||
//!
|
||||
//! [^1]: Returned by the [`Subscriber::register_callsite`][`register_callsite`]
|
||||
//! method.
|
||||
//!
|
||||
//! [`Metadata`]: crate::metadata::Metadata
|
||||
//! [`Interest`]: crate::subscriber::Interest
|
||||
//! [`Subscriber`]: crate::subscriber::Subscriber
|
||||
//! [`register_callsite`]: crate::subscriber::Subscriber::register_callsite
|
||||
//! [`Subscriber::enabled`]: crate::subscriber::Subscriber::enabled
|
||||
//! [always]: crate::subscriber::Interest::always
|
||||
//! [sometimes]: crate::subscriber::Interest::sometimes
|
||||
//! [never]: crate::subscriber::Interest::never
|
||||
//! [`Dispatch`]: crate::dispatch::Dispatch
|
||||
//! [macros]: https://docs.rs/tracing/latest/tracing/#macros
|
||||
//! [instrument]: https://docs.rs/tracing/latest/tracing/attr.instrument.html
|
||||
use crate::stdlib::{
|
||||
any::TypeId,
|
||||
fmt,
|
||||
hash::{Hash, Hasher},
|
||||
ptr,
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicPtr, AtomicU8, Ordering},
|
||||
Mutex,
|
||||
},
|
||||
vec::Vec,
|
||||
};
|
||||
use crate::{
|
||||
dispatcher::Dispatch,
|
||||
metadata::{LevelFilter, Metadata},
|
||||
subscriber::Interest,
|
||||
};
|
||||
|
||||
use self::dispatchers::Dispatchers;
|
||||
|
||||
/// Trait implemented by callsites.
|
||||
///
|
||||
/// These functions are only intended to be called by the callsite registry, which
|
||||
/// correctly handles determining the common interest between all subscribers.
|
||||
///
|
||||
/// See the [module-level documentation](crate::callsite) for details on
|
||||
/// callsites.
|
||||
pub trait Callsite: Sync {
|
||||
/// Sets the [`Interest`] for this callsite.
|
||||
///
|
||||
/// See the [documentation on callsite interest caching][cache-docs] for
|
||||
/// details.
|
||||
///
|
||||
/// [`Interest`]: super::subscriber::Interest
|
||||
/// [cache-docs]: crate::callsite#performing-static-filtering
|
||||
fn set_interest(&self, interest: Interest);
|
||||
|
||||
/// Returns the [metadata] associated with the callsite.
|
||||
///
|
||||
/// [metadata]: super::metadata::Metadata
|
||||
fn metadata(&self) -> &Metadata<'_>;
|
||||
|
||||
/// This method is an *internal implementation detail* of `tracing-core`. It
|
||||
/// is *not* intended to be called or overridden from downstream code.
|
||||
///
|
||||
/// The `Private` type can only be constructed from within `tracing-core`.
|
||||
/// Because this method takes a `Private` as an argument, it cannot be
|
||||
/// called from (safe) code external to `tracing-core`. Because it must
|
||||
/// *return* a `Private`, the only valid implementation possible outside of
|
||||
/// `tracing-core` would have to always unconditionally panic.
|
||||
///
|
||||
/// THIS IS BY DESIGN. There is currently no valid reason for code outside
|
||||
/// of `tracing-core` to override this method.
|
||||
// TODO(eliza): this could be used to implement a public downcasting API
|
||||
// for `&dyn Callsite`s in the future.
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
fn private_type_id(&self, _: private::Private<()>) -> private::Private<TypeId>
|
||||
where
|
||||
Self: 'static,
|
||||
{
|
||||
private::Private(TypeId::of::<Self>())
|
||||
}
|
||||
}
|
||||
|
||||
/// Uniquely identifies a [`Callsite`]
|
||||
///
|
||||
/// Two `Identifier`s are equal if they both refer to the same callsite.
|
||||
///
|
||||
/// [`Callsite`]: super::callsite::Callsite
|
||||
#[derive(Clone)]
|
||||
pub struct Identifier(
|
||||
/// **Warning**: The fields on this type are currently `pub` because it must
|
||||
/// be able to be constructed statically by macros. However, when `const
|
||||
/// fn`s are available on stable Rust, this will no longer be necessary.
|
||||
/// Thus, these fields are *not* considered stable public API, and they may
|
||||
/// change warning. Do not rely on any fields on `Identifier`. When
|
||||
/// constructing new `Identifier`s, use the `identify_callsite!` macro
|
||||
/// instead.
|
||||
#[doc(hidden)]
|
||||
pub &'static dyn Callsite,
|
||||
);
|
||||
|
||||
/// A default [`Callsite`] implementation.
|
||||
#[derive(Debug)]
|
||||
pub struct DefaultCallsite {
|
||||
interest: AtomicU8,
|
||||
registration: AtomicU8,
|
||||
meta: &'static Metadata<'static>,
|
||||
next: AtomicPtr<Self>,
|
||||
}
|
||||
|
||||
/// Clear and reregister interest on every [`Callsite`]
|
||||
///
|
||||
/// This function is intended for runtime reconfiguration of filters on traces
|
||||
/// when the filter recalculation is much less frequent than trace events are.
|
||||
/// The alternative is to have the [`Subscriber`] that supports runtime
|
||||
/// reconfiguration of filters always return [`Interest::sometimes()`] so that
|
||||
/// [`enabled`] is evaluated for every event.
|
||||
///
|
||||
/// This function will also re-compute the global maximum level as determined by
|
||||
/// the [`max_level_hint`] method. If a [`Subscriber`]
|
||||
/// implementation changes the value returned by its `max_level_hint`
|
||||
/// implementation at runtime, then it **must** call this function after that
|
||||
/// value changes, in order for the change to be reflected.
|
||||
///
|
||||
/// See the [documentation on callsite interest caching][cache-docs] for
|
||||
/// additional information on this function's usage.
|
||||
///
|
||||
/// [`max_level_hint`]: super::subscriber::Subscriber::max_level_hint
|
||||
/// [`Callsite`]: super::callsite::Callsite
|
||||
/// [`enabled`]: super::subscriber::Subscriber#tymethod.enabled
|
||||
/// [`Interest::sometimes()`]: super::subscriber::Interest::sometimes
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [cache-docs]: crate::callsite#rebuilding-cached-interest
|
||||
pub fn rebuild_interest_cache() {
|
||||
CALLSITES.rebuild_interest(DISPATCHERS.rebuilder());
|
||||
}
|
||||
|
||||
/// Register a new [`Callsite`] with the global registry.
|
||||
///
|
||||
/// This should be called once per callsite after the callsite has been
|
||||
/// constructed.
|
||||
///
|
||||
/// See the [documentation on callsite registration][reg-docs] for details
|
||||
/// on the global callsite registry.
|
||||
///
|
||||
/// [`Callsite`]: crate::callsite::Callsite
|
||||
/// [reg-docs]: crate::callsite#registering-callsites
|
||||
pub fn register(callsite: &'static dyn Callsite) {
|
||||
rebuild_callsite_interest(callsite, &DISPATCHERS.rebuilder());
|
||||
|
||||
// Is this a `DefaultCallsite`? If so, use the fancy linked list!
|
||||
if callsite.private_type_id(private::Private(())).0 == TypeId::of::<DefaultCallsite>() {
|
||||
let callsite = unsafe {
|
||||
// Safety: the pointer cast is safe because the type id of the
|
||||
// provided callsite matches that of the target type for the cast
|
||||
// (`DefaultCallsite`). Because user implementations of `Callsite`
|
||||
// cannot override `private_type_id`, we can trust that the callsite
|
||||
// is not lying about its type ID.
|
||||
&*(callsite as *const dyn Callsite as *const DefaultCallsite)
|
||||
};
|
||||
CALLSITES.push_default(callsite);
|
||||
return;
|
||||
}
|
||||
|
||||
CALLSITES.push_dyn(callsite);
|
||||
}
|
||||
|
||||
static CALLSITES: Callsites = Callsites {
|
||||
list_head: AtomicPtr::new(ptr::null_mut()),
|
||||
has_locked_callsites: AtomicBool::new(false),
|
||||
};
|
||||
|
||||
static DISPATCHERS: Dispatchers = Dispatchers::new();
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
static LOCKED_CALLSITES: once_cell::sync::Lazy<Mutex<Vec<&'static dyn Callsite>>> =
|
||||
once_cell::sync::Lazy::new(Default::default);
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
crate::lazy_static! {
|
||||
static ref LOCKED_CALLSITES: Mutex<Vec<&'static dyn Callsite>> = Mutex::new(Vec::new());
|
||||
}
|
||||
|
||||
struct Callsites {
|
||||
list_head: AtomicPtr<DefaultCallsite>,
|
||||
has_locked_callsites: AtomicBool,
|
||||
}
|
||||
|
||||
// === impl DefaultCallsite ===
|
||||
|
||||
impl DefaultCallsite {
|
||||
const UNREGISTERED: u8 = 0;
|
||||
const REGISTERING: u8 = 1;
|
||||
const REGISTERED: u8 = 2;
|
||||
|
||||
const INTEREST_NEVER: u8 = 0;
|
||||
const INTEREST_SOMETIMES: u8 = 1;
|
||||
const INTEREST_ALWAYS: u8 = 2;
|
||||
|
||||
/// Returns a new `DefaultCallsite` with the specified `Metadata`.
|
||||
pub const fn new(meta: &'static Metadata<'static>) -> Self {
|
||||
Self {
|
||||
interest: AtomicU8::new(0xFF),
|
||||
meta,
|
||||
next: AtomicPtr::new(ptr::null_mut()),
|
||||
registration: AtomicU8::new(Self::UNREGISTERED),
|
||||
}
|
||||
}
|
||||
|
||||
/// Registers this callsite with the global callsite registry.
|
||||
///
|
||||
/// If the callsite is already registered, this does nothing. When using
|
||||
/// [`DefaultCallsite`], this method should be preferred over
|
||||
/// [`tracing_core::callsite::register`], as it ensures that the callsite is
|
||||
/// only registered a single time.
|
||||
///
|
||||
/// Other callsite implementations will generally ensure that
|
||||
/// callsites are not re-registered through another mechanism.
|
||||
///
|
||||
/// See the [documentation on callsite registration][reg-docs] for details
|
||||
/// on the global callsite registry.
|
||||
///
|
||||
/// [`Callsite`]: crate::callsite::Callsite
|
||||
/// [reg-docs]: crate::callsite#registering-callsites
|
||||
#[inline(never)]
|
||||
// This only happens once (or if the cached interest value was corrupted).
|
||||
#[cold]
|
||||
pub fn register(&'static self) -> Interest {
|
||||
// Attempt to advance the registration state to `REGISTERING`...
|
||||
match self.registration.compare_exchange(
|
||||
Self::UNREGISTERED,
|
||||
Self::REGISTERING,
|
||||
Ordering::AcqRel,
|
||||
Ordering::Acquire,
|
||||
) {
|
||||
Ok(_) => {
|
||||
// Okay, we advanced the state, try to register the callsite.
|
||||
rebuild_callsite_interest(self, &DISPATCHERS.rebuilder());
|
||||
CALLSITES.push_default(self);
|
||||
self.registration.store(Self::REGISTERED, Ordering::Release);
|
||||
}
|
||||
// Great, the callsite is already registered! Just load its
|
||||
// previous cached interest.
|
||||
Err(Self::REGISTERED) => {}
|
||||
// Someone else is registering...
|
||||
Err(_state) => {
|
||||
debug_assert_eq!(
|
||||
_state,
|
||||
Self::REGISTERING,
|
||||
"weird callsite registration state"
|
||||
);
|
||||
// Just hit `enabled` this time.
|
||||
return Interest::sometimes();
|
||||
}
|
||||
}
|
||||
|
||||
match self.interest.load(Ordering::Relaxed) {
|
||||
Self::INTEREST_NEVER => Interest::never(),
|
||||
Self::INTEREST_ALWAYS => Interest::always(),
|
||||
_ => Interest::sometimes(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the callsite's cached `Interest`, or registers it for the
|
||||
/// first time if it has not yet been registered.
|
||||
#[inline]
|
||||
pub fn interest(&'static self) -> Interest {
|
||||
match self.interest.load(Ordering::Relaxed) {
|
||||
Self::INTEREST_NEVER => Interest::never(),
|
||||
Self::INTEREST_SOMETIMES => Interest::sometimes(),
|
||||
Self::INTEREST_ALWAYS => Interest::always(),
|
||||
_ => self.register(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Callsite for DefaultCallsite {
|
||||
fn set_interest(&self, interest: Interest) {
|
||||
let interest = match () {
|
||||
_ if interest.is_never() => Self::INTEREST_NEVER,
|
||||
_ if interest.is_always() => Self::INTEREST_ALWAYS,
|
||||
_ => Self::INTEREST_SOMETIMES,
|
||||
};
|
||||
self.interest.store(interest, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn metadata(&self) -> &Metadata<'static> {
|
||||
self.meta
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl Identifier =====
|
||||
|
||||
impl PartialEq for Identifier {
|
||||
fn eq(&self, other: &Identifier) -> bool {
|
||||
core::ptr::eq(
|
||||
self.0 as *const _ as *const (),
|
||||
other.0 as *const _ as *const (),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Identifier {}
|
||||
|
||||
impl fmt::Debug for Identifier {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Identifier({:p})", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Identifier {
|
||||
fn hash<H>(&self, state: &mut H)
|
||||
where
|
||||
H: Hasher,
|
||||
{
|
||||
(self.0 as *const dyn Callsite).hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
// === impl Callsites ===
|
||||
|
||||
impl Callsites {
|
||||
/// Rebuild `Interest`s for all callsites in the registry.
|
||||
///
|
||||
/// This also re-computes the max level hint.
|
||||
fn rebuild_interest(&self, dispatchers: dispatchers::Rebuilder<'_>) {
|
||||
let mut max_level = LevelFilter::OFF;
|
||||
dispatchers.for_each(|dispatch| {
|
||||
// If the subscriber did not provide a max level hint, assume
|
||||
// that it may enable every level.
|
||||
let level_hint = dispatch.max_level_hint().unwrap_or(LevelFilter::TRACE);
|
||||
if level_hint > max_level {
|
||||
max_level = level_hint;
|
||||
}
|
||||
});
|
||||
|
||||
self.for_each(|callsite| {
|
||||
rebuild_callsite_interest(callsite, &dispatchers);
|
||||
});
|
||||
LevelFilter::set_max(max_level);
|
||||
}
|
||||
|
||||
/// Push a `dyn Callsite` trait object to the callsite registry.
|
||||
///
|
||||
/// This will attempt to lock the callsites vector.
|
||||
fn push_dyn(&self, callsite: &'static dyn Callsite) {
|
||||
let mut lock = LOCKED_CALLSITES.lock().unwrap();
|
||||
self.has_locked_callsites.store(true, Ordering::Release);
|
||||
lock.push(callsite);
|
||||
}
|
||||
|
||||
/// Push a `DefaultCallsite` to the callsite registry.
|
||||
///
|
||||
/// If we know the callsite being pushed is a `DefaultCallsite`, we can push
|
||||
/// it to the linked list without having to acquire a lock.
|
||||
fn push_default(&self, callsite: &'static DefaultCallsite) {
|
||||
let mut head = self.list_head.load(Ordering::Acquire);
|
||||
|
||||
loop {
|
||||
callsite.next.store(head, Ordering::Release);
|
||||
|
||||
assert_ne!(
|
||||
callsite as *const _, head,
|
||||
"Attempted to register a `DefaultCallsite` that already exists! \
|
||||
This will cause an infinite loop when attempting to read from the \
|
||||
callsite cache. This is likely a bug! You should only need to call \
|
||||
`DefaultCallsite::register` once per `DefaultCallsite`."
|
||||
);
|
||||
|
||||
match self.list_head.compare_exchange(
|
||||
head,
|
||||
callsite as *const _ as *mut _,
|
||||
Ordering::AcqRel,
|
||||
Ordering::Acquire,
|
||||
) {
|
||||
Ok(_) => {
|
||||
break;
|
||||
}
|
||||
Err(current) => head = current,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Invokes the provided closure `f` with each callsite in the registry.
|
||||
fn for_each(&self, mut f: impl FnMut(&'static dyn Callsite)) {
|
||||
let mut head = self.list_head.load(Ordering::Acquire);
|
||||
|
||||
while let Some(cs) = unsafe { head.as_ref() } {
|
||||
f(cs);
|
||||
|
||||
head = cs.next.load(Ordering::Acquire);
|
||||
}
|
||||
|
||||
if self.has_locked_callsites.load(Ordering::Acquire) {
|
||||
let locked = LOCKED_CALLSITES.lock().unwrap();
|
||||
for &cs in locked.iter() {
|
||||
f(cs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn register_dispatch(dispatch: &Dispatch) {
|
||||
let dispatchers = DISPATCHERS.register_dispatch(dispatch);
|
||||
CALLSITES.rebuild_interest(dispatchers);
|
||||
}
|
||||
|
||||
fn rebuild_callsite_interest(
|
||||
callsite: &'static dyn Callsite,
|
||||
dispatchers: &dispatchers::Rebuilder<'_>,
|
||||
) {
|
||||
let meta = callsite.metadata();
|
||||
|
||||
let mut interest = None;
|
||||
dispatchers.for_each(|dispatch| {
|
||||
let this_interest = dispatch.register_callsite(meta);
|
||||
interest = match interest.take() {
|
||||
None => Some(this_interest),
|
||||
Some(that_interest) => Some(that_interest.and(this_interest)),
|
||||
}
|
||||
});
|
||||
|
||||
let interest = interest.unwrap_or_else(Interest::never);
|
||||
callsite.set_interest(interest)
|
||||
}
|
||||
|
||||
mod private {
|
||||
/// Don't call this function, it's private.
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct Private<T>(pub(crate) T);
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
mod dispatchers {
|
||||
use crate::dispatcher;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
RwLock, RwLockReadGuard, RwLockWriteGuard,
|
||||
};
|
||||
|
||||
pub(super) struct Dispatchers {
|
||||
has_just_one: AtomicBool,
|
||||
}
|
||||
|
||||
static LOCKED_DISPATCHERS: Lazy<RwLock<Vec<dispatcher::Registrar>>> =
|
||||
Lazy::new(Default::default);
|
||||
|
||||
pub(super) enum Rebuilder<'a> {
|
||||
JustOne,
|
||||
Read(RwLockReadGuard<'a, Vec<dispatcher::Registrar>>),
|
||||
Write(RwLockWriteGuard<'a, Vec<dispatcher::Registrar>>),
|
||||
}
|
||||
|
||||
impl Dispatchers {
|
||||
pub(super) const fn new() -> Self {
|
||||
Self {
|
||||
has_just_one: AtomicBool::new(true),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn rebuilder(&self) -> Rebuilder<'_> {
|
||||
if self.has_just_one.load(Ordering::SeqCst) {
|
||||
return Rebuilder::JustOne;
|
||||
}
|
||||
Rebuilder::Read(LOCKED_DISPATCHERS.read().unwrap())
|
||||
}
|
||||
|
||||
pub(super) fn register_dispatch(&self, dispatch: &dispatcher::Dispatch) -> Rebuilder<'_> {
|
||||
let mut dispatchers = LOCKED_DISPATCHERS.write().unwrap();
|
||||
dispatchers.retain(|d| d.upgrade().is_some());
|
||||
dispatchers.push(dispatch.registrar());
|
||||
self.has_just_one
|
||||
.store(dispatchers.len() <= 1, Ordering::SeqCst);
|
||||
Rebuilder::Write(dispatchers)
|
||||
}
|
||||
}
|
||||
|
||||
impl Rebuilder<'_> {
|
||||
pub(super) fn for_each(&self, mut f: impl FnMut(&dispatcher::Dispatch)) {
|
||||
let iter = match self {
|
||||
Rebuilder::JustOne => {
|
||||
dispatcher::get_default(f);
|
||||
return;
|
||||
}
|
||||
Rebuilder::Read(vec) => vec.iter(),
|
||||
Rebuilder::Write(vec) => vec.iter(),
|
||||
};
|
||||
iter.filter_map(dispatcher::Registrar::upgrade)
|
||||
.for_each(|dispatch| f(&dispatch))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
mod dispatchers {
|
||||
use crate::dispatcher;
|
||||
|
||||
pub(super) struct Dispatchers(());
|
||||
pub(super) struct Rebuilder<'a>(Option<&'a dispatcher::Dispatch>);
|
||||
|
||||
impl Dispatchers {
|
||||
pub(super) const fn new() -> Self {
|
||||
Self(())
|
||||
}
|
||||
|
||||
pub(super) fn rebuilder(&self) -> Rebuilder<'_> {
|
||||
Rebuilder(None)
|
||||
}
|
||||
|
||||
pub(super) fn register_dispatch<'dispatch>(
|
||||
&self,
|
||||
dispatch: &'dispatch dispatcher::Dispatch,
|
||||
) -> Rebuilder<'dispatch> {
|
||||
// nop; on no_std, there can only ever be one dispatcher
|
||||
Rebuilder(Some(dispatch))
|
||||
}
|
||||
}
|
||||
|
||||
impl Rebuilder<'_> {
|
||||
#[inline]
|
||||
pub(super) fn for_each(&self, mut f: impl FnMut(&dispatcher::Dispatch)) {
|
||||
if let Some(dispatch) = self.0 {
|
||||
// we are rebuilding the interest cache because a new dispatcher
|
||||
// is about to be set. on `no_std`, this should only happen
|
||||
// once, because the new dispatcher will be the global default.
|
||||
f(dispatch)
|
||||
} else {
|
||||
// otherwise, we are rebuilding the cache because the subscriber
|
||||
// configuration changed, so use the global default.
|
||||
// on no_std, there can only ever be one dispatcher
|
||||
dispatcher::get_default(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
896
zeroidc/vendor/tracing-core/src/dispatcher.rs
vendored
Normal file
896
zeroidc/vendor/tracing-core/src/dispatcher.rs
vendored
Normal file
@@ -0,0 +1,896 @@
|
||||
//! Dispatches trace events to [`Subscriber`]s.
|
||||
//!
|
||||
//! The _dispatcher_ is the component of the tracing system which is responsible
|
||||
//! for forwarding trace data from the instrumentation points that generate it
|
||||
//! to the subscriber that collects it.
|
||||
//!
|
||||
//! # Using the Trace Dispatcher
|
||||
//!
|
||||
//! Every thread in a program using `tracing` has a _default subscriber_. When
|
||||
//! events occur, or spans are created, they are dispatched to the thread's
|
||||
//! current subscriber.
|
||||
//!
|
||||
//! ## Setting the Default Subscriber
|
||||
//!
|
||||
//! By default, the current subscriber is an empty implementation that does
|
||||
//! nothing. To use a subscriber implementation, it must be set as the default.
|
||||
//! There are two methods for doing so: [`with_default`] and
|
||||
//! [`set_global_default`]. `with_default` sets the default subscriber for the
|
||||
//! duration of a scope, while `set_global_default` sets a default subscriber
|
||||
//! for the entire process.
|
||||
//!
|
||||
//! To use either of these functions, we must first wrap our subscriber in a
|
||||
//! [`Dispatch`], a cloneable, type-erased reference to a subscriber. For
|
||||
//! example:
|
||||
//! ```rust
|
||||
//! # pub struct FooSubscriber;
|
||||
//! # use tracing_core::{
|
||||
//! # dispatcher, Event, Metadata,
|
||||
//! # span::{Attributes, Id, Record}
|
||||
//! # };
|
||||
//! # impl tracing_core::Subscriber for FooSubscriber {
|
||||
//! # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) }
|
||||
//! # fn record(&self, _: &Id, _: &Record) {}
|
||||
//! # fn event(&self, _: &Event) {}
|
||||
//! # fn record_follows_from(&self, _: &Id, _: &Id) {}
|
||||
//! # fn enabled(&self, _: &Metadata) -> bool { false }
|
||||
//! # fn enter(&self, _: &Id) {}
|
||||
//! # fn exit(&self, _: &Id) {}
|
||||
//! # }
|
||||
//! # impl FooSubscriber { fn new() -> Self { FooSubscriber } }
|
||||
//! use dispatcher::Dispatch;
|
||||
//!
|
||||
//! let my_subscriber = FooSubscriber::new();
|
||||
//! let my_dispatch = Dispatch::new(my_subscriber);
|
||||
//! ```
|
||||
//! Then, we can use [`with_default`] to set our `Dispatch` as the default for
|
||||
//! the duration of a block:
|
||||
//! ```rust
|
||||
//! # pub struct FooSubscriber;
|
||||
//! # use tracing_core::{
|
||||
//! # dispatcher, Event, Metadata,
|
||||
//! # span::{Attributes, Id, Record}
|
||||
//! # };
|
||||
//! # impl tracing_core::Subscriber for FooSubscriber {
|
||||
//! # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) }
|
||||
//! # fn record(&self, _: &Id, _: &Record) {}
|
||||
//! # fn event(&self, _: &Event) {}
|
||||
//! # fn record_follows_from(&self, _: &Id, _: &Id) {}
|
||||
//! # fn enabled(&self, _: &Metadata) -> bool { false }
|
||||
//! # fn enter(&self, _: &Id) {}
|
||||
//! # fn exit(&self, _: &Id) {}
|
||||
//! # }
|
||||
//! # impl FooSubscriber { fn new() -> Self { FooSubscriber } }
|
||||
//! # let my_subscriber = FooSubscriber::new();
|
||||
//! # let my_dispatch = dispatcher::Dispatch::new(my_subscriber);
|
||||
//! // no default subscriber
|
||||
//!
|
||||
//! # #[cfg(feature = "std")]
|
||||
//! dispatcher::with_default(&my_dispatch, || {
|
||||
//! // my_subscriber is the default
|
||||
//! });
|
||||
//!
|
||||
//! // no default subscriber again
|
||||
//! ```
|
||||
//! It's important to note that `with_default` will not propagate the current
|
||||
//! thread's default subscriber to any threads spawned within the `with_default`
|
||||
//! block. To propagate the default subscriber to new threads, either use
|
||||
//! `with_default` from the new thread, or use `set_global_default`.
|
||||
//!
|
||||
//! As an alternative to `with_default`, we can use [`set_global_default`] to
|
||||
//! set a `Dispatch` as the default for all threads, for the lifetime of the
|
||||
//! program. For example:
|
||||
//! ```rust
|
||||
//! # pub struct FooSubscriber;
|
||||
//! # use tracing_core::{
|
||||
//! # dispatcher, Event, Metadata,
|
||||
//! # span::{Attributes, Id, Record}
|
||||
//! # };
|
||||
//! # impl tracing_core::Subscriber for FooSubscriber {
|
||||
//! # fn new_span(&self, _: &Attributes) -> Id { Id::from_u64(0) }
|
||||
//! # fn record(&self, _: &Id, _: &Record) {}
|
||||
//! # fn event(&self, _: &Event) {}
|
||||
//! # fn record_follows_from(&self, _: &Id, _: &Id) {}
|
||||
//! # fn enabled(&self, _: &Metadata) -> bool { false }
|
||||
//! # fn enter(&self, _: &Id) {}
|
||||
//! # fn exit(&self, _: &Id) {}
|
||||
//! # }
|
||||
//! # impl FooSubscriber { fn new() -> Self { FooSubscriber } }
|
||||
//! # let my_subscriber = FooSubscriber::new();
|
||||
//! # let my_dispatch = dispatcher::Dispatch::new(my_subscriber);
|
||||
//! // no default subscriber
|
||||
//!
|
||||
//! dispatcher::set_global_default(my_dispatch)
|
||||
//! // `set_global_default` will return an error if the global default
|
||||
//! // subscriber has already been set.
|
||||
//! .expect("global default was already set!");
|
||||
//!
|
||||
//! // `my_subscriber` is now the default
|
||||
//! ```
|
||||
//!
|
||||
//! <pre class="ignore" style="white-space:normal;font:inherit;">
|
||||
//! <strong>Note</strong>:the thread-local scoped dispatcher
|
||||
//! (<a href="#fn.with_default"><code>with_default</code></a>) requires the
|
||||
//! Rust standard library. <code>no_std</code> users should use
|
||||
//! <a href="#fn.set_global_default"><code>set_global_default</code></a>
|
||||
//! instead.
|
||||
//! </pre>
|
||||
//!
|
||||
//! ## Accessing the Default Subscriber
|
||||
//!
|
||||
//! A thread's current default subscriber can be accessed using the
|
||||
//! [`get_default`] function, which executes a closure with a reference to the
|
||||
//! currently default `Dispatch`. This is used primarily by `tracing`
|
||||
//! instrumentation.
|
||||
//!
|
||||
use crate::{
|
||||
callsite, span,
|
||||
subscriber::{self, NoSubscriber, Subscriber},
|
||||
Event, LevelFilter, Metadata,
|
||||
};
|
||||
|
||||
use crate::stdlib::{
|
||||
any::Any,
|
||||
fmt,
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
Arc,
|
||||
},
|
||||
};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use crate::stdlib::{
|
||||
cell::{Cell, RefCell, RefMut},
|
||||
error,
|
||||
sync::Weak,
|
||||
};
|
||||
|
||||
/// `Dispatch` trace data to a [`Subscriber`].
|
||||
///
|
||||
#[derive(Clone)]
|
||||
pub struct Dispatch {
|
||||
subscriber: Arc<dyn Subscriber + Send + Sync>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
thread_local! {
|
||||
static CURRENT_STATE: State = State {
|
||||
default: RefCell::new(None),
|
||||
can_enter: Cell::new(true),
|
||||
};
|
||||
}
|
||||
|
||||
static EXISTS: AtomicBool = AtomicBool::new(false);
|
||||
static GLOBAL_INIT: AtomicUsize = AtomicUsize::new(UNINITIALIZED);
|
||||
|
||||
const UNINITIALIZED: usize = 0;
|
||||
const INITIALIZING: usize = 1;
|
||||
const INITIALIZED: usize = 2;
|
||||
|
||||
static mut GLOBAL_DISPATCH: Option<Dispatch> = None;
|
||||
|
||||
/// The dispatch state of a thread.
|
||||
#[cfg(feature = "std")]
|
||||
struct State {
|
||||
/// This thread's current default dispatcher.
|
||||
default: RefCell<Option<Dispatch>>,
|
||||
/// Whether or not we can currently begin dispatching a trace event.
|
||||
///
|
||||
/// This is set to `false` when functions such as `enter`, `exit`, `event`,
|
||||
/// and `new_span` are called on this thread's default dispatcher, to
|
||||
/// prevent further trace events triggered inside those functions from
|
||||
/// creating an infinite recursion. When we finish handling a dispatch, this
|
||||
/// is set back to `true`.
|
||||
can_enter: Cell<bool>,
|
||||
}
|
||||
|
||||
/// While this guard is active, additional calls to subscriber functions on
|
||||
/// the default dispatcher will not be able to access the dispatch context.
|
||||
/// Dropping the guard will allow the dispatch context to be re-entered.
|
||||
#[cfg(feature = "std")]
|
||||
struct Entered<'a>(&'a State);
|
||||
|
||||
/// A guard that resets the current default dispatcher to the prior
|
||||
/// default dispatcher when dropped.
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
#[derive(Debug)]
|
||||
pub struct DefaultGuard(Option<Dispatch>);
|
||||
|
||||
/// Sets this dispatch as the default for the duration of a closure.
|
||||
///
|
||||
/// The default dispatcher is used when creating a new [span] or
|
||||
/// [`Event`].
|
||||
///
|
||||
/// <pre class="ignore" style="white-space:normal;font:inherit;">
|
||||
/// <strong>Note</strong>: This function required the Rust standard library.
|
||||
/// <code>no_std</code> users should use <a href="../fn.set_global_default.html">
|
||||
/// <code>set_global_default</code></a> instead.
|
||||
/// </pre>
|
||||
///
|
||||
/// [span]: super::span
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [`Event`]: super::event::Event
|
||||
/// [`set_global_default`]: super::set_global_default
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
pub fn with_default<T>(dispatcher: &Dispatch, f: impl FnOnce() -> T) -> T {
|
||||
// When this guard is dropped, the default dispatcher will be reset to the
|
||||
// prior default. Using this (rather than simply resetting after calling
|
||||
// `f`) ensures that we always reset to the prior dispatcher even if `f`
|
||||
// panics.
|
||||
let _guard = set_default(dispatcher);
|
||||
f()
|
||||
}
|
||||
|
||||
/// Sets the dispatch as the default dispatch for the duration of the lifetime
|
||||
/// of the returned DefaultGuard
|
||||
///
|
||||
/// <pre class="ignore" style="white-space:normal;font:inherit;">
|
||||
/// <strong>Note</strong>: This function required the Rust standard library.
|
||||
/// <code>no_std</code> users should use <a href="../fn.set_global_default.html">
|
||||
/// <code>set_global_default</code></a> instead.
|
||||
/// </pre>
|
||||
///
|
||||
/// [`set_global_default`]: super::set_global_default
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
#[must_use = "Dropping the guard unregisters the dispatcher."]
|
||||
pub fn set_default(dispatcher: &Dispatch) -> DefaultGuard {
|
||||
// When this guard is dropped, the default dispatcher will be reset to the
|
||||
// prior default. Using this ensures that we always reset to the prior
|
||||
// dispatcher even if the thread calling this function panics.
|
||||
State::set_default(dispatcher.clone())
|
||||
}
|
||||
|
||||
/// Sets this dispatch as the global default for the duration of the entire program.
|
||||
/// Will be used as a fallback if no thread-local dispatch has been set in a thread
|
||||
/// (using `with_default`.)
|
||||
///
|
||||
/// Can only be set once; subsequent attempts to set the global default will fail.
|
||||
/// Returns `Err` if the global default has already been set.
|
||||
///
|
||||
/// <div class="example-wrap" style="display:inline-block"><pre class="compile_fail" style="white-space:normal;font:inherit;">
|
||||
/// <strong>Warning</strong>: In general, libraries should <em>not</em> call
|
||||
/// <code>set_global_default()</code>! Doing so will cause conflicts when
|
||||
/// executables that depend on the library try to set the default later.
|
||||
/// </pre></div>
|
||||
///
|
||||
/// [span]: super::span
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [`Event`]: super::event::Event
|
||||
pub fn set_global_default(dispatcher: Dispatch) -> Result<(), SetGlobalDefaultError> {
|
||||
// if `compare_exchange` returns Result::Ok(_), then `new` has been set and
|
||||
// `current`—now the prior value—has been returned in the `Ok()` branch.
|
||||
if GLOBAL_INIT
|
||||
.compare_exchange(
|
||||
UNINITIALIZED,
|
||||
INITIALIZING,
|
||||
Ordering::SeqCst,
|
||||
Ordering::SeqCst,
|
||||
)
|
||||
.is_ok()
|
||||
{
|
||||
unsafe {
|
||||
GLOBAL_DISPATCH = Some(dispatcher);
|
||||
}
|
||||
GLOBAL_INIT.store(INITIALIZED, Ordering::SeqCst);
|
||||
EXISTS.store(true, Ordering::Release);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(SetGlobalDefaultError { _no_construct: () })
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if a `tracing` dispatcher has ever been set.
|
||||
///
|
||||
/// This may be used to completely elide trace points if tracing is not in use
|
||||
/// at all or has yet to be initialized.
|
||||
#[doc(hidden)]
|
||||
#[inline(always)]
|
||||
pub fn has_been_set() -> bool {
|
||||
EXISTS.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Returned if setting the global dispatcher fails.
|
||||
#[derive(Debug)]
|
||||
pub struct SetGlobalDefaultError {
|
||||
_no_construct: (),
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
|
||||
impl error::Error for SetGlobalDefaultError {}
|
||||
|
||||
/// 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
|
||||
/// called while inside of another `get_default`, that closure will be provided
|
||||
/// with `Dispatch::none` rather than the previously set dispatcher.
|
||||
///
|
||||
/// [dispatcher]: super::dispatcher::Dispatch
|
||||
#[cfg(feature = "std")]
|
||||
pub fn get_default<T, F>(mut f: F) -> T
|
||||
where
|
||||
F: FnMut(&Dispatch) -> T,
|
||||
{
|
||||
CURRENT_STATE
|
||||
.try_with(|state| {
|
||||
if let Some(entered) = state.enter() {
|
||||
return f(&*entered.current());
|
||||
}
|
||||
|
||||
f(&Dispatch::none())
|
||||
})
|
||||
.unwrap_or_else(|_| f(&Dispatch::none()))
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// called while inside of another `get_default`, that closure will be provided
|
||||
/// with `Dispatch::none` rather than the previously set dispatcher.
|
||||
///
|
||||
/// [dispatcher]: super::dispatcher::Dispatch
|
||||
#[cfg(feature = "std")]
|
||||
#[doc(hidden)]
|
||||
#[inline(never)]
|
||||
pub fn get_current<T>(f: impl FnOnce(&Dispatch) -> T) -> Option<T> {
|
||||
CURRENT_STATE
|
||||
.try_with(|state| {
|
||||
let entered = state.enter()?;
|
||||
Some(f(&*entered.current()))
|
||||
})
|
||||
.ok()?
|
||||
}
|
||||
|
||||
/// Executes a closure with a reference to the current [dispatcher].
|
||||
///
|
||||
/// [dispatcher]: super::dispatcher::Dispatch
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[doc(hidden)]
|
||||
pub fn get_current<T>(f: impl FnOnce(&Dispatch) -> T) -> Option<T> {
|
||||
let dispatch = get_global()?;
|
||||
Some(f(&dispatch))
|
||||
}
|
||||
|
||||
/// Executes a closure with a reference to the current [dispatcher].
|
||||
///
|
||||
/// [dispatcher]: super::dispatcher::Dispatch
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub fn get_default<T, F>(mut f: F) -> T
|
||||
where
|
||||
F: FnMut(&Dispatch) -> T,
|
||||
{
|
||||
if let Some(d) = get_global() {
|
||||
f(d)
|
||||
} else {
|
||||
f(&Dispatch::none())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_global() -> Option<&'static Dispatch> {
|
||||
if GLOBAL_INIT.load(Ordering::SeqCst) != INITIALIZED {
|
||||
return None;
|
||||
}
|
||||
unsafe {
|
||||
// This is safe given the invariant that setting the global dispatcher
|
||||
// also sets `GLOBAL_INIT` to `INITIALIZED`.
|
||||
Some(GLOBAL_DISPATCH.as_ref().expect(
|
||||
"invariant violated: GLOBAL_DISPATCH must be initialized before GLOBAL_INIT is set",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub(crate) struct Registrar(Weak<dyn Subscriber + Send + Sync>);
|
||||
|
||||
impl Dispatch {
|
||||
/// Returns a new `Dispatch` that discards events and spans.
|
||||
#[inline]
|
||||
pub fn none() -> Self {
|
||||
Dispatch {
|
||||
subscriber: Arc::new(NoSubscriber::default()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a `Dispatch` that forwards to the given [`Subscriber`].
|
||||
///
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
pub fn new<S>(subscriber: S) -> Self
|
||||
where
|
||||
S: Subscriber + Send + Sync + 'static,
|
||||
{
|
||||
let me = Dispatch {
|
||||
subscriber: Arc::new(subscriber),
|
||||
};
|
||||
callsite::register_dispatch(&me);
|
||||
me
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub(crate) fn registrar(&self) -> Registrar {
|
||||
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.
|
||||
///
|
||||
/// This calls the [`register_callsite`] function on the [`Subscriber`]
|
||||
/// that this `Dispatch` forwards to.
|
||||
///
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [`register_callsite`]: super::subscriber::Subscriber::register_callsite
|
||||
#[inline]
|
||||
pub fn register_callsite(&self, metadata: &'static Metadata<'static>) -> subscriber::Interest {
|
||||
self.subscriber.register_callsite(metadata)
|
||||
}
|
||||
|
||||
/// Returns the highest [verbosity level][level] that this [`Subscriber`] will
|
||||
/// enable, or `None`, if the subscriber does not implement level-based
|
||||
/// filtering or chooses not to implement this method.
|
||||
///
|
||||
/// This calls the [`max_level_hint`] function on the [`Subscriber`]
|
||||
/// that this `Dispatch` forwards to.
|
||||
///
|
||||
/// [level]: super::Level
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [`register_callsite`]: super::subscriber::Subscriber::max_level_hint
|
||||
// TODO(eliza): consider making this a public API?
|
||||
#[inline]
|
||||
pub(crate) fn max_level_hint(&self) -> Option<LevelFilter> {
|
||||
self.subscriber.max_level_hint()
|
||||
}
|
||||
|
||||
/// Record the construction of a new span, returning a new [ID] for the
|
||||
/// span being constructed.
|
||||
///
|
||||
/// This calls the [`new_span`] function on the [`Subscriber`] that this
|
||||
/// `Dispatch` forwards to.
|
||||
///
|
||||
/// [ID]: super::span::Id
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [`new_span`]: super::subscriber::Subscriber::new_span
|
||||
#[inline]
|
||||
pub fn new_span(&self, span: &span::Attributes<'_>) -> span::Id {
|
||||
self.subscriber.new_span(span)
|
||||
}
|
||||
|
||||
/// Record a set of values on a span.
|
||||
///
|
||||
/// This calls the [`record`] function on the [`Subscriber`] that this
|
||||
/// `Dispatch` forwards to.
|
||||
///
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [`record`]: super::subscriber::Subscriber::record
|
||||
#[inline]
|
||||
pub fn record(&self, span: &span::Id, values: &span::Record<'_>) {
|
||||
self.subscriber.record(span, values)
|
||||
}
|
||||
|
||||
/// Adds an indication that `span` follows from the span with the id
|
||||
/// `follows`.
|
||||
///
|
||||
/// This calls the [`record_follows_from`] function on the [`Subscriber`]
|
||||
/// that this `Dispatch` forwards to.
|
||||
///
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [`record_follows_from`]: super::subscriber::Subscriber::record_follows_from
|
||||
#[inline]
|
||||
pub fn record_follows_from(&self, span: &span::Id, follows: &span::Id) {
|
||||
self.subscriber.record_follows_from(span, follows)
|
||||
}
|
||||
|
||||
/// Returns true if a span with the specified [metadata] would be
|
||||
/// recorded.
|
||||
///
|
||||
/// This calls the [`enabled`] function on the [`Subscriber`] that this
|
||||
/// `Dispatch` forwards to.
|
||||
///
|
||||
/// [metadata]: super::metadata::Metadata
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [`enabled`]: super::subscriber::Subscriber::enabled
|
||||
#[inline]
|
||||
pub fn enabled(&self, metadata: &Metadata<'_>) -> bool {
|
||||
self.subscriber.enabled(metadata)
|
||||
}
|
||||
|
||||
/// Records that an [`Event`] has occurred.
|
||||
///
|
||||
/// This calls the [`event`] function on the [`Subscriber`] that this
|
||||
/// `Dispatch` forwards to.
|
||||
///
|
||||
/// [`Event`]: super::event::Event
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [`event`]: super::subscriber::Subscriber::event
|
||||
#[inline]
|
||||
pub fn event(&self, event: &Event<'_>) {
|
||||
self.subscriber.event(event)
|
||||
}
|
||||
|
||||
/// Records that a span has been can_enter.
|
||||
///
|
||||
/// This calls the [`enter`] function on the [`Subscriber`] that this
|
||||
/// `Dispatch` forwards to.
|
||||
///
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [`enter`]: super::subscriber::Subscriber::enter
|
||||
pub fn enter(&self, span: &span::Id) {
|
||||
self.subscriber.enter(span);
|
||||
}
|
||||
|
||||
/// Records that a span has been exited.
|
||||
///
|
||||
/// This calls the [`exit`] function on the [`Subscriber`] that this
|
||||
/// `Dispatch` forwards to.
|
||||
///
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [`exit`]: super::subscriber::Subscriber::exit
|
||||
pub fn exit(&self, span: &span::Id) {
|
||||
self.subscriber.exit(span);
|
||||
}
|
||||
|
||||
/// Notifies the subscriber that a [span ID] has been cloned.
|
||||
///
|
||||
/// This function must only be called with span IDs that were returned by
|
||||
/// this `Dispatch`'s [`new_span`] function. The `tracing` crate upholds
|
||||
/// this guarantee and any other libraries implementing instrumentation APIs
|
||||
/// must as well.
|
||||
///
|
||||
/// This calls the [`clone_span`] function on the `Subscriber` that this
|
||||
/// `Dispatch` forwards to.
|
||||
///
|
||||
/// [span ID]: super::span::Id
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [`clone_span`]: super::subscriber::Subscriber::clone_span
|
||||
/// [`new_span`]: super::subscriber::Subscriber::new_span
|
||||
#[inline]
|
||||
pub fn clone_span(&self, id: &span::Id) -> span::Id {
|
||||
self.subscriber.clone_span(id)
|
||||
}
|
||||
|
||||
/// Notifies the subscriber that a [span ID] has been dropped.
|
||||
///
|
||||
/// This function must only be called with span IDs that were returned by
|
||||
/// this `Dispatch`'s [`new_span`] function. The `tracing` crate upholds
|
||||
/// this guarantee and any other libraries implementing instrumentation APIs
|
||||
/// must as well.
|
||||
///
|
||||
/// This calls the [`drop_span`] function on the [`Subscriber`] that this
|
||||
/// `Dispatch` forwards to.
|
||||
///
|
||||
/// <pre class="compile_fail" style="white-space:normal;font:inherit;">
|
||||
/// <strong>Deprecated</strong>: The <a href="#method.try_close"><code>
|
||||
/// try_close</code></a> method is functionally identical, but returns
|
||||
/// <code>true</code> if the span is now closed. It should be used
|
||||
/// instead of this method.
|
||||
/// </pre>
|
||||
///
|
||||
/// [span ID]: super::span::Id
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [`drop_span`]: super::subscriber::Subscriber::drop_span
|
||||
/// [`new_span`]: super::subscriber::Subscriber::new_span
|
||||
/// [`try_close`]: Entered::try_close()
|
||||
#[inline]
|
||||
#[deprecated(since = "0.1.2", note = "use `Dispatch::try_close` instead")]
|
||||
pub fn drop_span(&self, id: span::Id) {
|
||||
#[allow(deprecated)]
|
||||
self.subscriber.drop_span(id);
|
||||
}
|
||||
|
||||
/// Notifies the subscriber that a [span ID] has been dropped, and returns
|
||||
/// `true` if there are now 0 IDs referring to that span.
|
||||
///
|
||||
/// This function must only be called with span IDs that were returned by
|
||||
/// this `Dispatch`'s [`new_span`] function. The `tracing` crate upholds
|
||||
/// this guarantee and any other libraries implementing instrumentation APIs
|
||||
/// must as well.
|
||||
///
|
||||
/// This calls the [`try_close`] function on the [`Subscriber`] that this
|
||||
/// `Dispatch` forwards to.
|
||||
///
|
||||
/// [span ID]: super::span::Id
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [`try_close`]: super::subscriber::Subscriber::try_close
|
||||
/// [`new_span`]: super::subscriber::Subscriber::new_span
|
||||
pub fn try_close(&self, id: span::Id) -> bool {
|
||||
self.subscriber.try_close(id)
|
||||
}
|
||||
|
||||
/// Returns a type representing this subscriber's view of the current span.
|
||||
///
|
||||
/// This calls the [`current`] function on the `Subscriber` that this
|
||||
/// `Dispatch` forwards to.
|
||||
///
|
||||
/// [`current`]: super::subscriber::Subscriber::current_span
|
||||
#[inline]
|
||||
pub fn current_span(&self) -> span::Current {
|
||||
self.subscriber.current_span()
|
||||
}
|
||||
|
||||
/// Returns `true` if this `Dispatch` forwards to a `Subscriber` of type
|
||||
/// `T`.
|
||||
#[inline]
|
||||
pub fn is<T: Any>(&self) -> bool {
|
||||
<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)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Dispatch {
|
||||
/// Returns the current default dispatcher
|
||||
fn default() -> Self {
|
||||
get_default(|default| default.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Dispatch {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Dispatch")
|
||||
.field(&format_args!("{:p}", self.subscriber))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<S> for Dispatch
|
||||
where
|
||||
S: Subscriber + Send + Sync + 'static,
|
||||
{
|
||||
#[inline]
|
||||
fn from(subscriber: S) -> Self {
|
||||
Dispatch::new(subscriber)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Registrar {
|
||||
pub(crate) fn upgrade(&self) -> Option<Dispatch> {
|
||||
self.0.upgrade().map(|subscriber| Dispatch { subscriber })
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl State =====
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl State {
|
||||
/// Replaces the current default dispatcher on this thread with the provided
|
||||
/// dispatcher.Any
|
||||
///
|
||||
/// Dropping the returned `ResetGuard` will reset the default dispatcher to
|
||||
/// the previous value.
|
||||
#[inline]
|
||||
fn set_default(new_dispatch: Dispatch) -> DefaultGuard {
|
||||
let prior = CURRENT_STATE
|
||||
.try_with(|state| {
|
||||
state.can_enter.set(true);
|
||||
state.default.replace(Some(new_dispatch))
|
||||
})
|
||||
.ok()
|
||||
.flatten();
|
||||
EXISTS.store(true, Ordering::Release);
|
||||
DefaultGuard(prior)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn enter(&self) -> Option<Entered<'_>> {
|
||||
if self.can_enter.replace(false) {
|
||||
Some(Entered(self))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl Entered =====
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<'a> Entered<'a> {
|
||||
#[inline]
|
||||
fn current(&self) -> RefMut<'a, Dispatch> {
|
||||
let default = self.0.default.borrow_mut();
|
||||
RefMut::map(default, |default| {
|
||||
default.get_or_insert_with(|| get_global().cloned().unwrap_or_else(Dispatch::none))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<'a> Drop for Entered<'a> {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
self.0.can_enter.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl DefaultGuard =====
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Drop for DefaultGuard {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
// Replace the dispatcher and then drop the old one outside
|
||||
// of the thread-local context. Dropping the dispatch may
|
||||
// lead to the drop of a subscriber which, in the process,
|
||||
// could then also attempt to access the same thread local
|
||||
// state -- causing a clash.
|
||||
let prev = CURRENT_STATE.try_with(|state| state.default.replace(self.0.take()));
|
||||
drop(prev)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
#[cfg(feature = "std")]
|
||||
use crate::stdlib::sync::atomic::{AtomicUsize, Ordering};
|
||||
use crate::{
|
||||
callsite::Callsite,
|
||||
metadata::{Kind, Level, Metadata},
|
||||
subscriber::Interest,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn dispatch_is() {
|
||||
let dispatcher = Dispatch::new(NoSubscriber::default());
|
||||
assert!(dispatcher.is::<NoSubscriber>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dispatch_downcasts() {
|
||||
let dispatcher = Dispatch::new(NoSubscriber::default());
|
||||
assert!(dispatcher.downcast_ref::<NoSubscriber>().is_some());
|
||||
}
|
||||
|
||||
struct TestCallsite;
|
||||
static TEST_CALLSITE: TestCallsite = TestCallsite;
|
||||
static TEST_META: Metadata<'static> = metadata! {
|
||||
name: "test",
|
||||
target: module_path!(),
|
||||
level: Level::DEBUG,
|
||||
fields: &[],
|
||||
callsite: &TEST_CALLSITE,
|
||||
kind: Kind::EVENT
|
||||
};
|
||||
|
||||
impl Callsite for TestCallsite {
|
||||
fn set_interest(&self, _: Interest) {}
|
||||
fn metadata(&self) -> &Metadata<'_> {
|
||||
&TEST_META
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "std")]
|
||||
fn events_dont_infinite_loop() {
|
||||
// This test ensures that an event triggered within a subscriber
|
||||
// won't cause an infinite loop of events.
|
||||
struct TestSubscriber;
|
||||
impl Subscriber for TestSubscriber {
|
||||
fn enabled(&self, _: &Metadata<'_>) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
|
||||
span::Id::from_u64(0xAAAA)
|
||||
}
|
||||
|
||||
fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
|
||||
|
||||
fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
|
||||
|
||||
fn event(&self, _: &Event<'_>) {
|
||||
static EVENTS: AtomicUsize = AtomicUsize::new(0);
|
||||
assert_eq!(
|
||||
EVENTS.fetch_add(1, Ordering::Relaxed),
|
||||
0,
|
||||
"event method called twice!"
|
||||
);
|
||||
Event::dispatch(&TEST_META, &TEST_META.fields().value_set(&[]))
|
||||
}
|
||||
|
||||
fn enter(&self, _: &span::Id) {}
|
||||
|
||||
fn exit(&self, _: &span::Id) {}
|
||||
}
|
||||
|
||||
with_default(&Dispatch::new(TestSubscriber), || {
|
||||
Event::dispatch(&TEST_META, &TEST_META.fields().value_set(&[]))
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "std")]
|
||||
fn spans_dont_infinite_loop() {
|
||||
// This test ensures that a span created within a subscriber
|
||||
// won't cause an infinite loop of new spans.
|
||||
|
||||
fn mk_span() {
|
||||
get_default(|current| {
|
||||
current.new_span(&span::Attributes::new(
|
||||
&TEST_META,
|
||||
&TEST_META.fields().value_set(&[]),
|
||||
))
|
||||
});
|
||||
}
|
||||
|
||||
struct TestSubscriber;
|
||||
impl Subscriber for TestSubscriber {
|
||||
fn enabled(&self, _: &Metadata<'_>) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
|
||||
static NEW_SPANS: AtomicUsize = AtomicUsize::new(0);
|
||||
assert_eq!(
|
||||
NEW_SPANS.fetch_add(1, Ordering::Relaxed),
|
||||
0,
|
||||
"new_span method called twice!"
|
||||
);
|
||||
mk_span();
|
||||
span::Id::from_u64(0xAAAA)
|
||||
}
|
||||
|
||||
fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
|
||||
|
||||
fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
|
||||
|
||||
fn event(&self, _: &Event<'_>) {}
|
||||
|
||||
fn enter(&self, _: &span::Id) {}
|
||||
|
||||
fn exit(&self, _: &span::Id) {}
|
||||
}
|
||||
|
||||
with_default(&Dispatch::new(TestSubscriber), mk_span)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_no_subscriber() {
|
||||
let default_dispatcher = Dispatch::default();
|
||||
assert!(default_dispatcher.is::<NoSubscriber>());
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn default_dispatch() {
|
||||
struct TestSubscriber;
|
||||
impl Subscriber for TestSubscriber {
|
||||
fn enabled(&self, _: &Metadata<'_>) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
|
||||
span::Id::from_u64(0xAAAA)
|
||||
}
|
||||
|
||||
fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
|
||||
|
||||
fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
|
||||
|
||||
fn event(&self, _: &Event<'_>) {}
|
||||
|
||||
fn enter(&self, _: &span::Id) {}
|
||||
|
||||
fn exit(&self, _: &span::Id) {}
|
||||
}
|
||||
let guard = set_default(&Dispatch::new(TestSubscriber));
|
||||
let default_dispatcher = Dispatch::default();
|
||||
assert!(default_dispatcher.is::<TestSubscriber>());
|
||||
|
||||
drop(guard);
|
||||
let default_dispatcher = Dispatch::default();
|
||||
assert!(default_dispatcher.is::<NoSubscriber>());
|
||||
}
|
||||
}
|
||||
128
zeroidc/vendor/tracing-core/src/event.rs
vendored
Normal file
128
zeroidc/vendor/tracing-core/src/event.rs
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
//! Events represent single points in time during the execution of a program.
|
||||
use crate::parent::Parent;
|
||||
use crate::span::Id;
|
||||
use crate::{field, Metadata};
|
||||
|
||||
/// `Event`s represent single points in time where something occurred during the
|
||||
/// execution of a program.
|
||||
///
|
||||
/// An `Event` can be compared to a log record in unstructured logging, but with
|
||||
/// two key differences:
|
||||
/// - `Event`s exist _within the context of a [span]_. Unlike log lines, they
|
||||
/// may be located within the trace tree, allowing visibility into the
|
||||
/// _temporal_ context in which the event occurred, as well as the source
|
||||
/// code location.
|
||||
/// - Like spans, `Event`s have structured key-value data known as _[fields]_,
|
||||
/// which may include textual message. In general, a majority of the data
|
||||
/// associated with an event should be in the event's fields rather than in
|
||||
/// the textual message, as the fields are more structured.
|
||||
///
|
||||
/// [span]: super::span
|
||||
/// [fields]: super::field
|
||||
#[derive(Debug)]
|
||||
pub struct Event<'a> {
|
||||
fields: &'a field::ValueSet<'a>,
|
||||
metadata: &'static Metadata<'static>,
|
||||
parent: Parent,
|
||||
}
|
||||
|
||||
impl<'a> Event<'a> {
|
||||
/// Constructs a new `Event` with the specified metadata and set of values,
|
||||
/// and observes it with the current subscriber.
|
||||
pub fn dispatch(metadata: &'static Metadata<'static>, fields: &'a field::ValueSet<'_>) {
|
||||
let event = Event::new(metadata, fields);
|
||||
crate::dispatcher::get_default(|current| {
|
||||
current.event(&event);
|
||||
});
|
||||
}
|
||||
|
||||
/// Returns a new `Event` in the current span, with the specified metadata
|
||||
/// and set of values.
|
||||
#[inline]
|
||||
pub fn new(metadata: &'static Metadata<'static>, fields: &'a field::ValueSet<'a>) -> Self {
|
||||
Event {
|
||||
fields,
|
||||
metadata,
|
||||
parent: Parent::Current,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a new `Event` as a child of the specified span, with the
|
||||
/// provided metadata and set of values.
|
||||
#[inline]
|
||||
pub fn new_child_of(
|
||||
parent: impl Into<Option<Id>>,
|
||||
metadata: &'static Metadata<'static>,
|
||||
fields: &'a field::ValueSet<'a>,
|
||||
) -> Self {
|
||||
let parent = match parent.into() {
|
||||
Some(p) => Parent::Explicit(p),
|
||||
None => Parent::Root,
|
||||
};
|
||||
Event {
|
||||
fields,
|
||||
metadata,
|
||||
parent,
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a new `Event` with the specified metadata and set of values,
|
||||
/// and observes it with the current subscriber and an explicit parent.
|
||||
pub fn child_of(
|
||||
parent: impl Into<Option<Id>>,
|
||||
metadata: &'static Metadata<'static>,
|
||||
fields: &'a field::ValueSet<'_>,
|
||||
) {
|
||||
let event = Self::new_child_of(parent, metadata, fields);
|
||||
crate::dispatcher::get_default(|current| {
|
||||
current.event(&event);
|
||||
});
|
||||
}
|
||||
|
||||
/// Visits all the fields on this `Event` with the specified [visitor].
|
||||
///
|
||||
/// [visitor]: super::field::Visit
|
||||
#[inline]
|
||||
pub fn record(&self, visitor: &mut dyn field::Visit) {
|
||||
self.fields.record(visitor);
|
||||
}
|
||||
|
||||
/// Returns an iterator over the set of values on this `Event`.
|
||||
pub fn fields(&self) -> field::Iter {
|
||||
self.fields.field_set().iter()
|
||||
}
|
||||
|
||||
/// Returns [metadata] describing this `Event`.
|
||||
///
|
||||
/// [metadata]: super::Metadata
|
||||
pub fn metadata(&self) -> &'static Metadata<'static> {
|
||||
self.metadata
|
||||
}
|
||||
|
||||
/// Returns true if the new event should be a root.
|
||||
pub fn is_root(&self) -> bool {
|
||||
matches!(self.parent, Parent::Root)
|
||||
}
|
||||
|
||||
/// Returns true if the new event's parent should be determined based on the
|
||||
/// current context.
|
||||
///
|
||||
/// If this is true and the current thread is currently inside a span, then
|
||||
/// that span should be the new event's parent. Otherwise, if the current
|
||||
/// thread is _not_ inside a span, then the new event will be the root of its
|
||||
/// own trace tree.
|
||||
pub fn is_contextual(&self) -> bool {
|
||||
matches!(self.parent, Parent::Current)
|
||||
}
|
||||
|
||||
/// Returns the new event's explicitly-specified parent, if there is one.
|
||||
///
|
||||
/// Otherwise (if the new event is a root or is a child of the current span),
|
||||
/// returns `None`.
|
||||
pub fn parent(&self) -> Option<&Id> {
|
||||
match self.parent {
|
||||
Parent::Explicit(ref p) => Some(p),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
1199
zeroidc/vendor/tracing-core/src/field.rs
vendored
Normal file
1199
zeroidc/vendor/tracing-core/src/field.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
26
zeroidc/vendor/tracing-core/src/lazy_static/LICENSE
vendored
Normal file
26
zeroidc/vendor/tracing-core/src/lazy_static/LICENSE
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
Copyright (c) 2010 The Rust Project Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
30
zeroidc/vendor/tracing-core/src/lazy_static/core_lazy.rs
vendored
Normal file
30
zeroidc/vendor/tracing-core/src/lazy_static/core_lazy.rs
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright 2016 lazy-static.rs Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use crate::spin::Once;
|
||||
|
||||
pub(crate) struct Lazy<T: Sync>(Once<T>);
|
||||
|
||||
impl<T: Sync> Lazy<T> {
|
||||
pub(crate) const INIT: Self = Lazy(Once::INIT);
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn get<F>(&'static self, builder: F) -> &T
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
self.0.call_once(builder)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __lazy_static_create {
|
||||
($NAME:ident, $T:ty) => {
|
||||
static $NAME: $crate::lazy_static::lazy::Lazy<$T> = $crate::lazy_static::lazy::Lazy::INIT;
|
||||
};
|
||||
}
|
||||
89
zeroidc/vendor/tracing-core/src/lazy_static/mod.rs
vendored
Normal file
89
zeroidc/vendor/tracing-core/src/lazy_static/mod.rs
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright 2016 lazy-static.rs Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
/*!
|
||||
A macro for declaring lazily evaluated statics.
|
||||
Using this macro, it is possible to have `static`s that require code to be
|
||||
executed at runtime in order to be initialized.
|
||||
This includes anything requiring heap allocations, like vectors or hash maps,
|
||||
as well as anything that requires function calls to be computed.
|
||||
*/
|
||||
|
||||
#[path = "core_lazy.rs"]
|
||||
pub(crate) mod lazy;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(crate) use core::ops::Deref as __Deref;
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __lazy_static_internal {
|
||||
// optional visibility restrictions are wrapped in `()` to allow for
|
||||
// explicitly passing otherwise implicit information about private items
|
||||
($(#[$attr:meta])* ($($vis:tt)*) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
|
||||
$crate::__lazy_static_internal!(@MAKE TY, $(#[$attr])*, ($($vis)*), $N);
|
||||
$crate::__lazy_static_internal!(@TAIL, $N : $T = $e);
|
||||
$crate::lazy_static!($($t)*);
|
||||
};
|
||||
(@TAIL, $N:ident : $T:ty = $e:expr) => {
|
||||
impl $crate::lazy_static::__Deref for $N {
|
||||
type Target = $T;
|
||||
fn deref(&self) -> &$T {
|
||||
#[inline(always)]
|
||||
fn __static_ref_initialize() -> $T { $e }
|
||||
|
||||
#[inline(always)]
|
||||
fn __stability() -> &'static $T {
|
||||
$crate::__lazy_static_create!(LAZY, $T);
|
||||
LAZY.get(__static_ref_initialize)
|
||||
}
|
||||
__stability()
|
||||
}
|
||||
}
|
||||
impl $crate::lazy_static::LazyStatic for $N {
|
||||
fn initialize(lazy: &Self) {
|
||||
let _ = &**lazy;
|
||||
}
|
||||
}
|
||||
};
|
||||
// `vis` is wrapped in `()` to prevent parsing ambiguity
|
||||
(@MAKE TY, $(#[$attr:meta])*, ($($vis:tt)*), $N:ident) => {
|
||||
#[allow(missing_copy_implementations)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[allow(dead_code)]
|
||||
$(#[$attr])*
|
||||
$($vis)* struct $N {__private_field: ()}
|
||||
#[doc(hidden)]
|
||||
$($vis)* static $N: $N = $N {__private_field: ()};
|
||||
};
|
||||
() => ()
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! lazy_static {
|
||||
($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
|
||||
// use `()` to explicitly forward the information about private items
|
||||
$crate::__lazy_static_internal!($(#[$attr])* () static ref $N : $T = $e; $($t)*);
|
||||
};
|
||||
($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
|
||||
$crate::__lazy_static_internal!($(#[$attr])* (pub) static ref $N : $T = $e; $($t)*);
|
||||
};
|
||||
($(#[$attr:meta])* pub ($($vis:tt)+) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
|
||||
$crate::__lazy_static_internal!($(#[$attr])* (pub ($($vis)+)) static ref $N : $T = $e; $($t)*);
|
||||
};
|
||||
() => ()
|
||||
}
|
||||
|
||||
/// Support trait for enabling a few common operation on lazy static values.
|
||||
///
|
||||
/// This is implemented by each defined lazy static, and
|
||||
/// used by the free functions in this crate.
|
||||
pub(crate) trait LazyStatic {
|
||||
#[doc(hidden)]
|
||||
fn initialize(lazy: &Self);
|
||||
}
|
||||
298
zeroidc/vendor/tracing-core/src/lib.rs
vendored
Normal file
298
zeroidc/vendor/tracing-core/src/lib.rs
vendored
Normal file
@@ -0,0 +1,298 @@
|
||||
//! Core primitives for `tracing`.
|
||||
//!
|
||||
//! [`tracing`] is a framework for instrumenting Rust programs to collect
|
||||
//! structured, event-based diagnostic information. This crate defines the core
|
||||
//! primitives of `tracing`.
|
||||
//!
|
||||
//! This crate provides:
|
||||
//!
|
||||
//! * [`span::Id`] identifies a span within the execution of a program.
|
||||
//!
|
||||
//! * [`Event`] represents a single event within a trace.
|
||||
//!
|
||||
//! * [`Subscriber`], the trait implemented to collect trace data.
|
||||
//!
|
||||
//! * [`Metadata`] and [`Callsite`] provide information describing spans and
|
||||
//! `Event`s.
|
||||
//!
|
||||
//! * [`Field`], [`FieldSet`], [`Value`], and [`ValueSet`] represent the
|
||||
//! structured data attached to a span.
|
||||
//!
|
||||
//! * [`Dispatch`] allows spans and events to be dispatched to `Subscriber`s.
|
||||
//!
|
||||
//! In addition, it defines the global callsite registry and per-thread current
|
||||
//! dispatcher which other components of the tracing system rely on.
|
||||
//!
|
||||
//! *Compiler support: [requires `rustc` 1.49+][msrv]*
|
||||
//!
|
||||
//! [msrv]: #supported-rust-versions
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! Application authors will typically not use this crate directly. Instead,
|
||||
//! they will use the [`tracing`] crate, which provides a much more
|
||||
//! fully-featured API. However, this crate's API will change very infrequently,
|
||||
//! so it may be used when dependencies must be very stable.
|
||||
//!
|
||||
//! `Subscriber` implementations may depend on `tracing-core` rather than
|
||||
//! `tracing`, as the additional APIs provided by `tracing` are primarily useful
|
||||
//! for instrumenting libraries and applications, and are generally not
|
||||
//! necessary for `Subscriber` implementations.
|
||||
//!
|
||||
//! The [`tokio-rs/tracing`] repository contains less stable crates designed to
|
||||
//! be used with the `tracing` ecosystem. It includes a collection of
|
||||
//! `Subscriber` implementations, as well as utility and adapter crates.
|
||||
//!
|
||||
//! ## Crate Feature Flags
|
||||
//!
|
||||
//! The following crate [feature flags] are available:
|
||||
//!
|
||||
//! * `std`: Depend on the Rust standard library (enabled by default).
|
||||
//!
|
||||
//! `no_std` users may disable this feature with `default-features = false`:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! tracing-core = { version = "0.1.22", default-features = false }
|
||||
//! ```
|
||||
//!
|
||||
//! **Note**:`tracing-core`'s `no_std` support requires `liballoc`.
|
||||
//!
|
||||
//! ### Unstable Features
|
||||
//!
|
||||
//! These feature flags enable **unstable** features. The public API may break in 0.1.x
|
||||
//! releases. To enable these features, the `--cfg tracing_unstable` must be passed to
|
||||
//! `rustc` when compiling.
|
||||
//!
|
||||
//! The following unstable feature flags are currently available:
|
||||
//!
|
||||
//! * `valuable`: Enables support for recording [field values] using the
|
||||
//! [`valuable`] crate.
|
||||
//!
|
||||
//! #### Enabling Unstable Features
|
||||
//!
|
||||
//! The easiest way to set the `tracing_unstable` cfg is to use the `RUSTFLAGS`
|
||||
//! env variable when running `cargo` commands:
|
||||
//!
|
||||
//! ```shell
|
||||
//! RUSTFLAGS="--cfg tracing_unstable" cargo build
|
||||
//! ```
|
||||
//! Alternatively, the following can be added to the `.cargo/config` file in a
|
||||
//! project to automatically enable the cfg flag for that project:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [build]
|
||||
//! rustflags = ["--cfg", "tracing_unstable"]
|
||||
//! ```
|
||||
//!
|
||||
//! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
|
||||
//! [field values]: crate::field
|
||||
//! [`valuable`]: https://crates.io/crates/valuable
|
||||
//!
|
||||
//! ## Supported Rust Versions
|
||||
//!
|
||||
//! Tracing is built against the latest stable release. The minimum supported
|
||||
//! version is 1.49. The current Tracing version is not guaranteed to build on
|
||||
//! Rust versions earlier than the minimum supported version.
|
||||
//!
|
||||
//! Tracing follows the same compiler support policies as the rest of the Tokio
|
||||
//! project. The current stable Rust compiler and the three most recent minor
|
||||
//! versions before it will always be supported. For example, if the current
|
||||
//! stable compiler version is 1.45, the minimum supported version will not be
|
||||
//! increased past 1.42, three minor versions prior. Increasing the minimum
|
||||
//! supported compiler version is not considered a semver breaking change as
|
||||
//! long as doing so complies with this policy.
|
||||
//!
|
||||
//!
|
||||
//! [`span::Id`]: span::Id
|
||||
//! [`Event`]: event::Event
|
||||
//! [`Subscriber`]: subscriber::Subscriber
|
||||
//! [`Metadata`]: metadata::Metadata
|
||||
//! [`Callsite`]: callsite::Callsite
|
||||
//! [`Field`]: field::Field
|
||||
//! [`FieldSet`]: field::FieldSet
|
||||
//! [`Value`]: field::Value
|
||||
//! [`ValueSet`]: field::ValueSet
|
||||
//! [`Dispatch`]: dispatcher::Dispatch
|
||||
//! [`tokio-rs/tracing`]: https://github.com/tokio-rs/tracing
|
||||
//! [`tracing`]: https://crates.io/crates/tracing
|
||||
#![doc(html_root_url = "https://docs.rs/tracing-core/0.1.22")]
|
||||
#![doc(
|
||||
html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
|
||||
issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
|
||||
)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))]
|
||||
#![warn(
|
||||
missing_debug_implementations,
|
||||
missing_docs,
|
||||
rust_2018_idioms,
|
||||
unreachable_pub,
|
||||
bad_style,
|
||||
const_err,
|
||||
dead_code,
|
||||
improper_ctypes,
|
||||
non_shorthand_field_patterns,
|
||||
no_mangle_generic_items,
|
||||
overflowing_literals,
|
||||
path_statements,
|
||||
patterns_in_fns_without_body,
|
||||
private_in_public,
|
||||
unconditional_recursion,
|
||||
unused,
|
||||
unused_allocation,
|
||||
unused_comparisons,
|
||||
unused_parens,
|
||||
while_true
|
||||
)]
|
||||
#[cfg(not(feature = "std"))]
|
||||
extern crate alloc;
|
||||
|
||||
/// Statically constructs an [`Identifier`] for the provided [`Callsite`].
|
||||
///
|
||||
/// This may be used in contexts such as static initializers.
|
||||
///
|
||||
/// For example:
|
||||
/// ```rust
|
||||
/// use tracing_core::{callsite, identify_callsite};
|
||||
/// # use tracing_core::{Metadata, subscriber::Interest};
|
||||
/// # fn main() {
|
||||
/// pub struct MyCallsite {
|
||||
/// // ...
|
||||
/// }
|
||||
/// impl callsite::Callsite for MyCallsite {
|
||||
/// # fn set_interest(&self, _: Interest) { unimplemented!() }
|
||||
/// # fn metadata(&self) -> &Metadata { unimplemented!() }
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// static CALLSITE: MyCallsite = MyCallsite {
|
||||
/// // ...
|
||||
/// };
|
||||
///
|
||||
/// static CALLSITE_ID: callsite::Identifier = identify_callsite!(&CALLSITE);
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// [`Identifier`]: callsite::Identifier
|
||||
/// [`Callsite`]: callsite::Callsite
|
||||
#[macro_export]
|
||||
macro_rules! identify_callsite {
|
||||
($callsite:expr) => {
|
||||
$crate::callsite::Identifier($callsite)
|
||||
};
|
||||
}
|
||||
|
||||
/// Statically constructs new span [metadata].
|
||||
///
|
||||
/// /// For example:
|
||||
/// ```rust
|
||||
/// # use tracing_core::{callsite::Callsite, subscriber::Interest};
|
||||
/// use tracing_core::metadata;
|
||||
/// use tracing_core::metadata::{Kind, Level, Metadata};
|
||||
/// # fn main() {
|
||||
/// # pub struct MyCallsite { }
|
||||
/// # impl Callsite for MyCallsite {
|
||||
/// # fn set_interest(&self, _: Interest) { unimplemented!() }
|
||||
/// # fn metadata(&self) -> &Metadata { unimplemented!() }
|
||||
/// # }
|
||||
/// #
|
||||
/// static FOO_CALLSITE: MyCallsite = MyCallsite {
|
||||
/// // ...
|
||||
/// };
|
||||
///
|
||||
/// static FOO_METADATA: Metadata = metadata!{
|
||||
/// name: "foo",
|
||||
/// target: module_path!(),
|
||||
/// level: Level::DEBUG,
|
||||
/// fields: &["bar", "baz"],
|
||||
/// callsite: &FOO_CALLSITE,
|
||||
/// kind: Kind::SPAN,
|
||||
/// };
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// [metadata]: metadata::Metadata
|
||||
/// [`Metadata::new`]: metadata::Metadata::new
|
||||
#[macro_export]
|
||||
macro_rules! metadata {
|
||||
(
|
||||
name: $name:expr,
|
||||
target: $target:expr,
|
||||
level: $level:expr,
|
||||
fields: $fields:expr,
|
||||
callsite: $callsite:expr,
|
||||
kind: $kind:expr
|
||||
) => {
|
||||
$crate::metadata! {
|
||||
name: $name,
|
||||
target: $target,
|
||||
level: $level,
|
||||
fields: $fields,
|
||||
callsite: $callsite,
|
||||
kind: $kind,
|
||||
}
|
||||
};
|
||||
(
|
||||
name: $name:expr,
|
||||
target: $target:expr,
|
||||
level: $level:expr,
|
||||
fields: $fields:expr,
|
||||
callsite: $callsite:expr,
|
||||
kind: $kind:expr,
|
||||
) => {
|
||||
$crate::metadata::Metadata::new(
|
||||
$name,
|
||||
$target,
|
||||
$level,
|
||||
Some(file!()),
|
||||
Some(line!()),
|
||||
Some(module_path!()),
|
||||
$crate::field::FieldSet::new($fields, $crate::identify_callsite!($callsite)),
|
||||
$kind,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
// Facade module: `no_std` uses spinlocks, `std` uses the mutexes in the standard library
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[macro_use]
|
||||
mod lazy_static;
|
||||
|
||||
// Trimmed-down vendored version of spin 0.5.2 (0387621)
|
||||
// Dependency of no_std lazy_static, not required in a std build
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub(crate) mod spin;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[doc(hidden)]
|
||||
pub type Once = self::spin::Once<()>;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use stdlib::sync::Once;
|
||||
|
||||
pub mod callsite;
|
||||
pub mod dispatcher;
|
||||
pub mod event;
|
||||
pub mod field;
|
||||
pub mod metadata;
|
||||
mod parent;
|
||||
pub mod span;
|
||||
pub(crate) mod stdlib;
|
||||
pub mod subscriber;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use self::{
|
||||
callsite::Callsite,
|
||||
dispatcher::Dispatch,
|
||||
event::Event,
|
||||
field::Field,
|
||||
metadata::{Level, LevelFilter, Metadata},
|
||||
subscriber::Subscriber,
|
||||
};
|
||||
|
||||
pub use self::{metadata::Kind, subscriber::Interest};
|
||||
|
||||
mod sealed {
|
||||
pub trait Sealed {}
|
||||
}
|
||||
1061
zeroidc/vendor/tracing-core/src/metadata.rs
vendored
Normal file
1061
zeroidc/vendor/tracing-core/src/metadata.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
11
zeroidc/vendor/tracing-core/src/parent.rs
vendored
Normal file
11
zeroidc/vendor/tracing-core/src/parent.rs
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
use crate::span::Id;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum Parent {
|
||||
/// The new span will be a root span.
|
||||
Root,
|
||||
/// The new span will be rooted in the current span.
|
||||
Current,
|
||||
/// The new span has an explicitly-specified parent.
|
||||
Explicit(Id),
|
||||
}
|
||||
341
zeroidc/vendor/tracing-core/src/span.rs
vendored
Normal file
341
zeroidc/vendor/tracing-core/src/span.rs
vendored
Normal file
@@ -0,0 +1,341 @@
|
||||
//! Spans represent periods of time in the execution of a program.
|
||||
use crate::field::FieldSet;
|
||||
use crate::parent::Parent;
|
||||
use crate::stdlib::num::NonZeroU64;
|
||||
use crate::{field, Metadata};
|
||||
|
||||
/// Identifies a span within the context of a subscriber.
|
||||
///
|
||||
/// They are generated by [`Subscriber`]s for each span as it is created, by
|
||||
/// the [`new_span`] trait method. See the documentation for that method for
|
||||
/// more information on span ID generation.
|
||||
///
|
||||
/// [`Subscriber`]: super::subscriber::Subscriber
|
||||
/// [`new_span`]: super::subscriber::Subscriber::new_span
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Id(NonZeroU64);
|
||||
|
||||
/// Attributes provided to a `Subscriber` describing a new span when it is
|
||||
/// created.
|
||||
#[derive(Debug)]
|
||||
pub struct Attributes<'a> {
|
||||
metadata: &'static Metadata<'static>,
|
||||
values: &'a field::ValueSet<'a>,
|
||||
parent: Parent,
|
||||
}
|
||||
|
||||
/// A set of fields recorded by a span.
|
||||
#[derive(Debug)]
|
||||
pub struct Record<'a> {
|
||||
values: &'a field::ValueSet<'a>,
|
||||
}
|
||||
|
||||
/// Indicates what [the `Subscriber` considers] the "current" span.
|
||||
///
|
||||
/// As subscribers may not track a notion of a current span, this has three
|
||||
/// possible states:
|
||||
/// - "unknown", indicating that the subscriber does not track a current span,
|
||||
/// - "none", indicating that the current context is known to not be in a span,
|
||||
/// - "some", with the current span's [`Id`] and [`Metadata`].
|
||||
///
|
||||
/// [the `Subscriber` considers]: super::subscriber::Subscriber::current_span
|
||||
/// [`Metadata`]: super::metadata::Metadata
|
||||
#[derive(Debug)]
|
||||
pub struct Current {
|
||||
inner: CurrentInner,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum CurrentInner {
|
||||
Current {
|
||||
id: Id,
|
||||
metadata: &'static Metadata<'static>,
|
||||
},
|
||||
None,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
// ===== impl Span =====
|
||||
|
||||
impl Id {
|
||||
/// Constructs a new span ID from the given `u64`.
|
||||
///
|
||||
/// <pre class="ignore" style="white-space:normal;font:inherit;">
|
||||
/// <strong>Note</strong>: Span IDs must be greater than zero.
|
||||
/// </pre>
|
||||
///
|
||||
/// # Panics
|
||||
/// - If the provided `u64` is 0.
|
||||
pub fn from_u64(u: u64) -> Self {
|
||||
Id(NonZeroU64::new(u).expect("span IDs must be > 0"))
|
||||
}
|
||||
|
||||
/// Constructs a new span ID from the given `NonZeroU64`.
|
||||
///
|
||||
/// Unlike [`Id::from_u64`](Id::from_u64()), this will never panic.
|
||||
#[inline]
|
||||
pub const fn from_non_zero_u64(id: NonZeroU64) -> Self {
|
||||
Id(id)
|
||||
}
|
||||
|
||||
// Allow `into` by-ref since we don't want to impl Copy for Id
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
/// Returns the span's ID as a `u64`.
|
||||
pub fn into_u64(&self) -> u64 {
|
||||
self.0.get()
|
||||
}
|
||||
|
||||
// Allow `into` by-ref since we don't want to impl Copy for Id
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
/// Returns the span's ID as a `NonZeroU64`.
|
||||
#[inline]
|
||||
pub const fn into_non_zero_u64(&self) -> NonZeroU64 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Id> for Option<Id> {
|
||||
fn from(id: &'a Id) -> Self {
|
||||
Some(id.clone())
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl Attributes =====
|
||||
|
||||
impl<'a> Attributes<'a> {
|
||||
/// Returns `Attributes` describing a new child span of the current span,
|
||||
/// with the provided metadata and values.
|
||||
pub fn new(metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>) -> Self {
|
||||
Attributes {
|
||||
metadata,
|
||||
values,
|
||||
parent: Parent::Current,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `Attributes` describing a new span at the root of its own trace
|
||||
/// tree, with the provided metadata and values.
|
||||
pub fn new_root(metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>) -> Self {
|
||||
Attributes {
|
||||
metadata,
|
||||
values,
|
||||
parent: Parent::Root,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `Attributes` describing a new child span of the specified
|
||||
/// parent span, with the provided metadata and values.
|
||||
pub fn child_of(
|
||||
parent: Id,
|
||||
metadata: &'static Metadata<'static>,
|
||||
values: &'a field::ValueSet<'a>,
|
||||
) -> Self {
|
||||
Attributes {
|
||||
metadata,
|
||||
values,
|
||||
parent: Parent::Explicit(parent),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the new span's metadata.
|
||||
pub fn metadata(&self) -> &'static Metadata<'static> {
|
||||
self.metadata
|
||||
}
|
||||
|
||||
/// Returns a reference to a `ValueSet` containing any values the new span
|
||||
/// was created with.
|
||||
pub fn values(&self) -> &field::ValueSet<'a> {
|
||||
self.values
|
||||
}
|
||||
|
||||
/// Returns true if the new span should be a root.
|
||||
pub fn is_root(&self) -> bool {
|
||||
matches!(self.parent, Parent::Root)
|
||||
}
|
||||
|
||||
/// Returns true if the new span's parent should be determined based on the
|
||||
/// current context.
|
||||
///
|
||||
/// If this is true and the current thread is currently inside a span, then
|
||||
/// that span should be the new span's parent. Otherwise, if the current
|
||||
/// thread is _not_ inside a span, then the new span will be the root of its
|
||||
/// own trace tree.
|
||||
pub fn is_contextual(&self) -> bool {
|
||||
matches!(self.parent, Parent::Current)
|
||||
}
|
||||
|
||||
/// Returns the new span's explicitly-specified parent, if there is one.
|
||||
///
|
||||
/// Otherwise (if the new span is a root or is a child of the current span),
|
||||
/// returns `None`.
|
||||
pub fn parent(&self) -> Option<&Id> {
|
||||
match self.parent {
|
||||
Parent::Explicit(ref p) => Some(p),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Records all the fields in this set of `Attributes` with the provided
|
||||
/// [Visitor].
|
||||
///
|
||||
/// [visitor]: super::field::Visit
|
||||
pub fn record(&self, visitor: &mut dyn field::Visit) {
|
||||
self.values.record(visitor)
|
||||
}
|
||||
|
||||
/// Returns `true` if this set of `Attributes` contains a value for the
|
||||
/// given `Field`.
|
||||
pub fn contains(&self, field: &field::Field) -> bool {
|
||||
self.values.contains(field)
|
||||
}
|
||||
|
||||
/// Returns true if this set of `Attributes` contains _no_ values.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.values.is_empty()
|
||||
}
|
||||
|
||||
/// Returns the set of all [fields] defined by this span's [`Metadata`].
|
||||
///
|
||||
/// Note that the [`FieldSet`] returned by this method includes *all* the
|
||||
/// fields declared by this span, not just those with values that are recorded
|
||||
/// as part of this set of `Attributes`. Other fields with values not present in
|
||||
/// this `Attributes`' value set may [record] values later.
|
||||
///
|
||||
/// [fields]: crate::field
|
||||
/// [record]: Attributes::record()
|
||||
/// [`Metadata`]: crate::metadata::Metadata
|
||||
/// [`FieldSet`]: crate::field::FieldSet
|
||||
pub fn fields(&self) -> &FieldSet {
|
||||
self.values.field_set()
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl Record =====
|
||||
|
||||
impl<'a> Record<'a> {
|
||||
/// Constructs a new `Record` from a `ValueSet`.
|
||||
pub fn new(values: &'a field::ValueSet<'a>) -> Self {
|
||||
Self { values }
|
||||
}
|
||||
|
||||
/// Records all the fields in this `Record` with the provided [Visitor].
|
||||
///
|
||||
/// [visitor]: super::field::Visit
|
||||
pub fn record(&self, visitor: &mut dyn field::Visit) {
|
||||
self.values.record(visitor)
|
||||
}
|
||||
|
||||
/// Returns the number of fields that would be visited from this `Record`
|
||||
/// when [`Record::record()`] is called
|
||||
///
|
||||
/// [`Record::record()`]: Record::record()
|
||||
pub fn len(&self) -> usize {
|
||||
self.values.len()
|
||||
}
|
||||
|
||||
/// Returns `true` if this `Record` contains a value for the given `Field`.
|
||||
pub fn contains(&self, field: &field::Field) -> bool {
|
||||
self.values.contains(field)
|
||||
}
|
||||
|
||||
/// Returns true if this `Record` contains _no_ values.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.values.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl Current =====
|
||||
|
||||
impl Current {
|
||||
/// Constructs a new `Current` that indicates the current context is a span
|
||||
/// with the given `metadata` and `metadata`.
|
||||
pub fn new(id: Id, metadata: &'static Metadata<'static>) -> Self {
|
||||
Self {
|
||||
inner: CurrentInner::Current { id, metadata },
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a new `Current` that indicates the current context is *not*
|
||||
/// in a span.
|
||||
pub fn none() -> Self {
|
||||
Self {
|
||||
inner: CurrentInner::None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a new `Current` that indicates the `Subscriber` does not
|
||||
/// track a current span.
|
||||
pub(crate) fn unknown() -> Self {
|
||||
Self {
|
||||
inner: CurrentInner::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the `Subscriber` that constructed this `Current` tracks a
|
||||
/// current span.
|
||||
///
|
||||
/// If this returns `true` and [`id`], [`metadata`], or [`into_inner`]
|
||||
/// return `None`, that indicates that we are currently known to *not* be
|
||||
/// inside a span. If this returns `false`, those methods will also return
|
||||
/// `None`, but in this case, that is because the subscriber does not keep
|
||||
/// track of the currently-entered span.
|
||||
///
|
||||
/// [`id`]: Current::id()
|
||||
/// [`metadata`]: Current::metadata()
|
||||
/// [`into_inner`]: Current::into_inner()
|
||||
pub fn is_known(&self) -> bool {
|
||||
!matches!(self.inner, CurrentInner::Unknown)
|
||||
}
|
||||
|
||||
/// Consumes `self` and returns the span `Id` and `Metadata` of the current
|
||||
/// span, if one exists and is known.
|
||||
pub fn into_inner(self) -> Option<(Id, &'static Metadata<'static>)> {
|
||||
match self.inner {
|
||||
CurrentInner::Current { id, metadata } => Some((id, metadata)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Borrows the `Id` of the current span, if one exists and is known.
|
||||
pub fn id(&self) -> Option<&Id> {
|
||||
match self.inner {
|
||||
CurrentInner::Current { ref id, .. } => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Borrows the `Metadata` of the current span, if one exists and is known.
|
||||
pub fn metadata(&self) -> Option<&'static Metadata<'static>> {
|
||||
match self.inner {
|
||||
CurrentInner::Current { metadata, .. } => Some(metadata),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Current> for Option<&'a Id> {
|
||||
fn from(cur: &'a Current) -> Self {
|
||||
cur.id()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Current> for Option<Id> {
|
||||
fn from(cur: &'a Current) -> Self {
|
||||
cur.id().cloned()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Current> for Option<Id> {
|
||||
fn from(cur: Current) -> Self {
|
||||
match cur.inner {
|
||||
CurrentInner::Current { id, .. } => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Current> for Option<&'static Metadata<'static>> {
|
||||
fn from(cur: &'a Current) -> Self {
|
||||
cur.metadata()
|
||||
}
|
||||
}
|
||||
21
zeroidc/vendor/tracing-core/src/spin/LICENSE
vendored
Normal file
21
zeroidc/vendor/tracing-core/src/spin/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Mathijs van de Nes
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
7
zeroidc/vendor/tracing-core/src/spin/mod.rs
vendored
Normal file
7
zeroidc/vendor/tracing-core/src/spin/mod.rs
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
//! Synchronization primitives based on spinning
|
||||
|
||||
pub(crate) use mutex::*;
|
||||
pub(crate) use once::Once;
|
||||
|
||||
mod mutex;
|
||||
mod once;
|
||||
118
zeroidc/vendor/tracing-core/src/spin/mutex.rs
vendored
Normal file
118
zeroidc/vendor/tracing-core/src/spin/mutex.rs
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
use core::cell::UnsafeCell;
|
||||
use core::default::Default;
|
||||
use core::fmt;
|
||||
use core::hint;
|
||||
use core::marker::Sync;
|
||||
use core::ops::{Deref, DerefMut, Drop};
|
||||
use core::option::Option::{self, None, Some};
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
/// This type provides MUTual EXclusion based on spinning.
|
||||
pub(crate) struct Mutex<T: ?Sized> {
|
||||
lock: AtomicBool,
|
||||
data: UnsafeCell<T>,
|
||||
}
|
||||
|
||||
/// A guard to which the protected data can be accessed
|
||||
///
|
||||
/// When the guard falls out of scope it will release the lock.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct MutexGuard<'a, T: ?Sized> {
|
||||
lock: &'a AtomicBool,
|
||||
data: &'a mut T,
|
||||
}
|
||||
|
||||
// Same unsafe impls as `std::sync::Mutex`
|
||||
unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {}
|
||||
unsafe impl<T: ?Sized + Send> Send for Mutex<T> {}
|
||||
|
||||
impl<T> Mutex<T> {
|
||||
/// Creates a new spinlock wrapping the supplied data.
|
||||
pub(crate) const fn new(user_data: T) -> Mutex<T> {
|
||||
Mutex {
|
||||
lock: AtomicBool::new(false),
|
||||
data: UnsafeCell::new(user_data),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Mutex<T> {
|
||||
fn obtain_lock(&self) {
|
||||
while self
|
||||
.lock
|
||||
.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
|
||||
.is_err()
|
||||
{
|
||||
// Wait until the lock looks unlocked before retrying
|
||||
while self.lock.load(Ordering::Relaxed) {
|
||||
hint::spin_loop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Locks the spinlock and returns a guard.
|
||||
///
|
||||
/// The returned value may be dereferenced for data access
|
||||
/// and the lock will be dropped when the guard falls out of scope.
|
||||
pub(crate) fn lock(&self) -> MutexGuard<'_, T> {
|
||||
self.obtain_lock();
|
||||
MutexGuard {
|
||||
lock: &self.lock,
|
||||
data: unsafe { &mut *self.data.get() },
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to lock the mutex. If it is already locked, it will return None. Otherwise it returns
|
||||
/// a guard within Some.
|
||||
pub(crate) fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
|
||||
if self
|
||||
.lock
|
||||
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
|
||||
.is_ok()
|
||||
{
|
||||
Some(MutexGuard {
|
||||
lock: &self.lock,
|
||||
data: unsafe { &mut *self.data.get() },
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.try_lock() {
|
||||
Some(guard) => write!(f, "Mutex {{ data: ")
|
||||
.and_then(|()| (&*guard).fmt(f))
|
||||
.and_then(|()| write!(f, "}}")),
|
||||
None => write!(f, "Mutex {{ <locked> }}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Default> Default for Mutex<T> {
|
||||
fn default() -> Mutex<T> {
|
||||
Mutex::new(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> {
|
||||
type Target = T;
|
||||
fn deref<'b>(&'b self) -> &'b T {
|
||||
&*self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> {
|
||||
fn deref_mut<'b>(&'b mut self) -> &'b mut T {
|
||||
&mut *self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
|
||||
/// The dropping of the MutexGuard will release the lock it was created from.
|
||||
fn drop(&mut self) {
|
||||
self.lock.store(false, Ordering::Release);
|
||||
}
|
||||
}
|
||||
158
zeroidc/vendor/tracing-core/src/spin/once.rs
vendored
Normal file
158
zeroidc/vendor/tracing-core/src/spin/once.rs
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
use core::cell::UnsafeCell;
|
||||
use core::fmt;
|
||||
use core::hint::spin_loop;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
/// A synchronization primitive which can be used to run a one-time global
|
||||
/// initialization. Unlike its std equivalent, this is generalized so that the
|
||||
/// closure returns a value and it is stored. Once therefore acts something like
|
||||
/// a future, too.
|
||||
pub struct Once<T> {
|
||||
state: AtomicUsize,
|
||||
data: UnsafeCell<Option<T>>, // TODO remove option and use mem::uninitialized
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug> fmt::Debug for Once<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.r#try() {
|
||||
Some(s) => write!(f, "Once {{ data: ")
|
||||
.and_then(|()| s.fmt(f))
|
||||
.and_then(|()| write!(f, "}}")),
|
||||
None => write!(f, "Once {{ <uninitialized> }}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Same unsafe impls as `std::sync::RwLock`, because this also allows for
|
||||
// concurrent reads.
|
||||
unsafe impl<T: Send + Sync> Sync for Once<T> {}
|
||||
unsafe impl<T: Send> Send for Once<T> {}
|
||||
|
||||
// Four states that a Once can be in, encoded into the lower bits of `state` in
|
||||
// the Once structure.
|
||||
const INCOMPLETE: usize = 0x0;
|
||||
const RUNNING: usize = 0x1;
|
||||
const COMPLETE: usize = 0x2;
|
||||
const PANICKED: usize = 0x3;
|
||||
|
||||
use core::hint::unreachable_unchecked as unreachable;
|
||||
|
||||
impl<T> Once<T> {
|
||||
/// Initialization constant of `Once`.
|
||||
pub const INIT: Self = Once {
|
||||
state: AtomicUsize::new(INCOMPLETE),
|
||||
data: UnsafeCell::new(None),
|
||||
};
|
||||
|
||||
/// Creates a new `Once` value.
|
||||
pub const fn new() -> Once<T> {
|
||||
Self::INIT
|
||||
}
|
||||
|
||||
fn force_get<'a>(&'a self) -> &'a T {
|
||||
match unsafe { &*self.data.get() }.as_ref() {
|
||||
None => unsafe { unreachable() },
|
||||
Some(p) => p,
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs an initialization routine once and only once. The given closure
|
||||
/// will be executed if this is the first time `call_once` has been called,
|
||||
/// and otherwise the routine will *not* be invoked.
|
||||
///
|
||||
/// This method will block the calling thread if another initialization
|
||||
/// routine is currently running.
|
||||
///
|
||||
/// When this function returns, it is guaranteed that some initialization
|
||||
/// has run and completed (it may not be the closure specified). The
|
||||
/// returned pointer will point to the result from the closure that was
|
||||
/// run.
|
||||
pub fn call_once<'a, F>(&'a self, builder: F) -> &'a T
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
let mut status = self.state.load(Ordering::SeqCst);
|
||||
|
||||
if status == INCOMPLETE {
|
||||
status = match self.state.compare_exchange(
|
||||
INCOMPLETE,
|
||||
RUNNING,
|
||||
Ordering::SeqCst,
|
||||
Ordering::SeqCst,
|
||||
) {
|
||||
Ok(status) => {
|
||||
debug_assert_eq!(
|
||||
status, INCOMPLETE,
|
||||
"if compare_exchange succeeded, previous status must be incomplete",
|
||||
);
|
||||
// We init
|
||||
// We use a guard (Finish) to catch panics caused by builder
|
||||
let mut finish = Finish {
|
||||
state: &self.state,
|
||||
panicked: true,
|
||||
};
|
||||
unsafe { *self.data.get() = Some(builder()) };
|
||||
finish.panicked = false;
|
||||
|
||||
self.state.store(COMPLETE, Ordering::SeqCst);
|
||||
|
||||
// This next line is strictly an optimization
|
||||
return self.force_get();
|
||||
}
|
||||
Err(status) => status,
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
match status {
|
||||
INCOMPLETE => unreachable!(),
|
||||
RUNNING => {
|
||||
// We spin
|
||||
spin_loop();
|
||||
status = self.state.load(Ordering::SeqCst)
|
||||
}
|
||||
PANICKED => panic!("Once has panicked"),
|
||||
COMPLETE => return self.force_get(),
|
||||
_ => unsafe { unreachable() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a pointer iff the `Once` was previously initialized
|
||||
pub fn r#try<'a>(&'a self) -> Option<&'a T> {
|
||||
match self.state.load(Ordering::SeqCst) {
|
||||
COMPLETE => Some(self.force_get()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Like try, but will spin if the `Once` is in the process of being
|
||||
/// initialized
|
||||
pub fn wait<'a>(&'a self) -> Option<&'a T> {
|
||||
loop {
|
||||
match self.state.load(Ordering::SeqCst) {
|
||||
INCOMPLETE => return None,
|
||||
|
||||
RUNNING => {
|
||||
spin_loop() // We spin
|
||||
}
|
||||
COMPLETE => return Some(self.force_get()),
|
||||
PANICKED => panic!("Once has panicked"),
|
||||
_ => unsafe { unreachable() },
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Finish<'a> {
|
||||
state: &'a AtomicUsize,
|
||||
panicked: bool,
|
||||
}
|
||||
|
||||
impl<'a> Drop for Finish<'a> {
|
||||
fn drop(&mut self) {
|
||||
if self.panicked {
|
||||
self.state.store(PANICKED, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
}
|
||||
78
zeroidc/vendor/tracing-core/src/stdlib.rs
vendored
Normal file
78
zeroidc/vendor/tracing-core/src/stdlib.rs
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
//! Re-exports either the Rust `std` library or `core` and `alloc` when `std` is
|
||||
//! disabled.
|
||||
//!
|
||||
//! `crate::stdlib::...` should be used rather than `std::` when adding code that
|
||||
//! will be available with the standard library disabled.
|
||||
//!
|
||||
//! Note that this module is called `stdlib` rather than `std`, as Rust 1.34.0
|
||||
//! does not permit redefining the name `stdlib` (although this works on the
|
||||
//! latest stable Rust).
|
||||
#[cfg(feature = "std")]
|
||||
pub(crate) use std::*;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub(crate) use self::no_std::*;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
mod no_std {
|
||||
// We pre-emptively export everything from libcore/liballoc, (even modules
|
||||
// we aren't using currently) to make adding new code easier. Therefore,
|
||||
// some of these imports will be unused.
|
||||
#![allow(unused_imports)]
|
||||
|
||||
pub(crate) use core::{
|
||||
any, array, ascii, cell, char, clone, cmp, convert, default, f32, f64, ffi, future, hash,
|
||||
hint, i128, i16, i8, isize, iter, marker, mem, num, ops, option, pin, ptr, result, task,
|
||||
time, u128, u16, u32, u8, usize,
|
||||
};
|
||||
|
||||
pub(crate) use alloc::{boxed, collections, rc, string, vec};
|
||||
|
||||
pub(crate) mod borrow {
|
||||
pub(crate) use alloc::borrow::*;
|
||||
pub(crate) use core::borrow::*;
|
||||
}
|
||||
|
||||
pub(crate) mod fmt {
|
||||
pub(crate) use alloc::fmt::*;
|
||||
pub(crate) use core::fmt::*;
|
||||
}
|
||||
|
||||
pub(crate) mod slice {
|
||||
pub(crate) use alloc::slice::*;
|
||||
pub(crate) use core::slice::*;
|
||||
}
|
||||
|
||||
pub(crate) mod str {
|
||||
pub(crate) use alloc::str::*;
|
||||
pub(crate) use core::str::*;
|
||||
}
|
||||
|
||||
pub(crate) mod sync {
|
||||
pub(crate) use crate::spin::MutexGuard;
|
||||
pub(crate) use alloc::sync::*;
|
||||
pub(crate) use core::sync::*;
|
||||
|
||||
/// This wraps `spin::Mutex` to return a `Result`, so that it can be
|
||||
/// used with code written against `std::sync::Mutex`.
|
||||
///
|
||||
/// Since `spin::Mutex` doesn't support poisoning, the `Result` returned
|
||||
/// by `lock` will always be `Ok`.
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct Mutex<T> {
|
||||
inner: crate::spin::Mutex<T>,
|
||||
}
|
||||
|
||||
impl<T> Mutex<T> {
|
||||
pub(crate) fn new(data: T) -> Self {
|
||||
Self {
|
||||
inner: crate::spin::Mutex::new(data),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn lock(&self) -> Result<MutexGuard<'_, T>, ()> {
|
||||
Ok(self.inner.lock())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
757
zeroidc/vendor/tracing-core/src/subscriber.rs
vendored
Normal file
757
zeroidc/vendor/tracing-core/src/subscriber.rs
vendored
Normal file
@@ -0,0 +1,757 @@
|
||||
//! Subscribers collect and record trace data.
|
||||
use crate::{span, Event, LevelFilter, Metadata};
|
||||
|
||||
use crate::stdlib::{
|
||||
any::{Any, TypeId},
|
||||
boxed::Box,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
/// Trait representing the functions required to collect trace data.
|
||||
///
|
||||
/// Crates that provide implementations of methods for collecting or recording
|
||||
/// trace data should implement the `Subscriber` interface. This trait is
|
||||
/// intended to represent fundamental primitives for collecting trace events and
|
||||
/// spans — other libraries may offer utility functions and types to make
|
||||
/// subscriber implementations more modular or improve the ergonomics of writing
|
||||
/// subscribers.
|
||||
///
|
||||
/// A subscriber is responsible for the following:
|
||||
/// - Registering new spans as they are created, and providing them with span
|
||||
/// IDs. Implicitly, this means the subscriber may determine the strategy for
|
||||
/// determining span equality.
|
||||
/// - Recording the attachment of field values and follows-from annotations to
|
||||
/// spans.
|
||||
/// - Filtering spans and events, and determining when those filters must be
|
||||
/// invalidated.
|
||||
/// - Observing spans as they are entered, exited, and closed, and events as
|
||||
/// they occur.
|
||||
///
|
||||
/// When a span is entered or exited, the subscriber is provided only with the
|
||||
/// [ID] with which it tagged that span when it was created. This means
|
||||
/// that it is up to the subscriber to determine whether and how span _data_ —
|
||||
/// the fields and metadata describing the span — should be stored. The
|
||||
/// [`new_span`] function is called when a new span is created, and at that
|
||||
/// point, the subscriber _may_ choose to store the associated data if it will
|
||||
/// be referenced again. However, if the data has already been recorded and will
|
||||
/// not be needed by the implementations of `enter` and `exit`, the subscriber
|
||||
/// may freely discard that data without allocating space to store it.
|
||||
///
|
||||
/// ## Overriding default impls
|
||||
///
|
||||
/// Some trait methods on `Subscriber` have default implementations, either in
|
||||
/// order to reduce the surface area of implementing `Subscriber`, or for
|
||||
/// backward-compatibility reasons. However, many subscribers will likely want
|
||||
/// to override these default implementations.
|
||||
///
|
||||
/// The following methods are likely of interest:
|
||||
///
|
||||
/// - [`register_callsite`] is called once for each callsite from which a span
|
||||
/// event may originate, and returns an [`Interest`] value describing whether or
|
||||
/// not the subscriber wishes to see events or spans from that callsite. By
|
||||
/// default, it calls [`enabled`], and returns `Interest::always()` if
|
||||
/// `enabled` returns true, or `Interest::never()` if enabled returns false.
|
||||
/// However, if the subscriber's interest can change dynamically at runtime,
|
||||
/// it may want to override this function to return `Interest::sometimes()`.
|
||||
/// Additionally, subscribers which wish to perform a behaviour once for each
|
||||
/// callsite, such as allocating storage for data related to that callsite,
|
||||
/// can perform it in `register_callsite`.
|
||||
///
|
||||
/// See also the [documentation on the callsite registry][cs-reg] for details
|
||||
/// on [`register_callsite`].
|
||||
///
|
||||
/// - [`clone_span`] is called every time a span ID is cloned, and [`try_close`]
|
||||
/// is called when a span ID is dropped. By default, these functions do
|
||||
/// nothing. However, they can be used to implement reference counting for
|
||||
/// spans, allowing subscribers to free storage for span data and to determine
|
||||
/// when a span has _closed_ permanently (rather than being exited).
|
||||
/// Subscribers which store per-span data or which need to track span closures
|
||||
/// should override these functions together.
|
||||
///
|
||||
/// [ID]: super::span::Id
|
||||
/// [`new_span`]: Subscriber::new_span
|
||||
/// [`register_callsite`]: Subscriber::register_callsite
|
||||
/// [`enabled`]: Subscriber::enabled
|
||||
/// [`clone_span`]: Subscriber::clone_span
|
||||
/// [`try_close`]: Subscriber::try_close
|
||||
/// [cs-reg]: crate::callsite#registering-callsites
|
||||
pub trait Subscriber: 'static {
|
||||
// === Span registry methods ==============================================
|
||||
|
||||
/// Registers a new [callsite] with this subscriber, returning whether or not
|
||||
/// the subscriber is interested in being notified about the callsite.
|
||||
///
|
||||
/// By default, this function assumes that the subscriber's [filter]
|
||||
/// represents an unchanging view of its interest in the callsite. However,
|
||||
/// if this is not the case, subscribers may override this function to
|
||||
/// indicate different interests, or to implement behaviour that should run
|
||||
/// once for every callsite.
|
||||
///
|
||||
/// This function is guaranteed to be called at least once per callsite on
|
||||
/// every active subscriber. The subscriber may store the keys to fields it
|
||||
/// cares about in order to reduce the cost of accessing fields by name,
|
||||
/// preallocate storage for that callsite, or perform any other actions it
|
||||
/// wishes to perform once for each callsite.
|
||||
///
|
||||
/// The subscriber should then return an [`Interest`], indicating
|
||||
/// whether it is interested in being notified about that callsite in the
|
||||
/// future. This may be `Always` indicating that the subscriber always
|
||||
/// wishes to be notified about the callsite, and its filter need not be
|
||||
/// re-evaluated; `Sometimes`, indicating that the subscriber may sometimes
|
||||
/// care about the callsite but not always (such as when sampling), or
|
||||
/// `Never`, indicating that the subscriber never wishes to be notified about
|
||||
/// that callsite. If all active subscribers return `Never`, a callsite will
|
||||
/// never be enabled unless a new subscriber expresses interest in it.
|
||||
///
|
||||
/// `Subscriber`s which require their filters to be run every time an event
|
||||
/// occurs or a span is entered/exited should return `Interest::sometimes`.
|
||||
/// If a subscriber returns `Interest::sometimes`, then its [`enabled`] method
|
||||
/// will be called every time an event or span is created from that callsite.
|
||||
///
|
||||
/// For example, suppose a sampling subscriber is implemented by
|
||||
/// incrementing a counter every time `enabled` is called and only returning
|
||||
/// `true` when the counter is divisible by a specified sampling rate. If
|
||||
/// that subscriber returns `Interest::always` from `register_callsite`, then
|
||||
/// the filter will not be re-evaluated once it has been applied to a given
|
||||
/// set of metadata. Thus, the counter will not be incremented, and the span
|
||||
/// or event that corresponds to the metadata will never be `enabled`.
|
||||
///
|
||||
/// `Subscriber`s that need to change their filters occasionally should call
|
||||
/// [`rebuild_interest_cache`] to re-evaluate `register_callsite` for all
|
||||
/// callsites.
|
||||
///
|
||||
/// Similarly, if a `Subscriber` has a filtering strategy that can be
|
||||
/// changed dynamically at runtime, it would need to re-evaluate that filter
|
||||
/// if the cached results have changed.
|
||||
///
|
||||
/// A subscriber which manages fanout to multiple other subscribers
|
||||
/// should proxy this decision to all of its child subscribers,
|
||||
/// returning `Interest::never` only if _all_ such children return
|
||||
/// `Interest::never`. If the set of subscribers to which spans are
|
||||
/// broadcast may change dynamically, the subscriber should also never
|
||||
/// return `Interest::Never`, as a new subscriber may be added that _is_
|
||||
/// interested.
|
||||
///
|
||||
/// See the [documentation on the callsite registry][cs-reg] for more
|
||||
/// details on how and when the `register_callsite` method is called.
|
||||
///
|
||||
/// # Notes
|
||||
/// This function may be called again when a new subscriber is created or
|
||||
/// when the registry is invalidated.
|
||||
///
|
||||
/// If a subscriber returns `Interest::never` for a particular callsite, it
|
||||
/// _may_ still see spans and events originating from that callsite, if
|
||||
/// another subscriber expressed interest in it.
|
||||
///
|
||||
/// [callsite]: crate::callsite
|
||||
/// [filter]: Self::enabled
|
||||
/// [metadata]: super::metadata::Metadata
|
||||
/// [`enabled`]: Subscriber::enabled()
|
||||
/// [`rebuild_interest_cache`]: super::callsite::rebuild_interest_cache
|
||||
/// [cs-reg]: crate::callsite#registering-callsites
|
||||
fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
|
||||
if self.enabled(metadata) {
|
||||
Interest::always()
|
||||
} else {
|
||||
Interest::never()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if a span or event with the specified [metadata] would be
|
||||
/// recorded.
|
||||
///
|
||||
/// By default, it is assumed that this filter needs only be evaluated once
|
||||
/// for each callsite, so it is called by [`register_callsite`] when each
|
||||
/// callsite is registered. The result is used to determine if the subscriber
|
||||
/// is always [interested] or never interested in that callsite. This is intended
|
||||
/// primarily as an optimization, so that expensive filters (such as those
|
||||
/// involving string search, et cetera) need not be re-evaluated.
|
||||
///
|
||||
/// However, if the subscriber's interest in a particular span or event may
|
||||
/// change, or depends on contexts only determined dynamically at runtime,
|
||||
/// then the `register_callsite` method should be overridden to return
|
||||
/// [`Interest::sometimes`]. In that case, this function will be called every
|
||||
/// time that span or event occurs.
|
||||
///
|
||||
/// [metadata]: super::metadata::Metadata
|
||||
/// [interested]: Interest
|
||||
/// [`Interest::sometimes`]: Interest::sometimes
|
||||
/// [`register_callsite`]: Subscriber::register_callsite()
|
||||
fn enabled(&self, metadata: &Metadata<'_>) -> bool;
|
||||
|
||||
/// Returns the highest [verbosity level][level] that this `Subscriber` will
|
||||
/// enable, or `None`, if the subscriber does not implement level-based
|
||||
/// filtering or chooses not to implement this method.
|
||||
///
|
||||
/// If this method returns a [`Level`][level], it will be used as a hint to
|
||||
/// determine the most verbose level that will be enabled. This will allow
|
||||
/// spans and events which are more verbose than that level to be skipped
|
||||
/// more efficiently. Subscribers which perform filtering are strongly
|
||||
/// encouraged to provide an implementation of this method.
|
||||
///
|
||||
/// If the maximum level the subscriber will enable can change over the
|
||||
/// course of its lifetime, it is free to return a different value from
|
||||
/// multiple invocations of this method. However, note that changes in the
|
||||
/// maximum level will **only** be reflected after the callsite [`Interest`]
|
||||
/// cache is rebuilt, by calling the [`callsite::rebuild_interest_cache`][rebuild]
|
||||
/// function. Therefore, if the subscriber will change the value returned by
|
||||
/// this method, it is responsible for ensuring that
|
||||
/// [`rebuild_interest_cache`][rebuild] is called after the value of the max
|
||||
/// level changes.
|
||||
///
|
||||
/// [level]: super::Level
|
||||
/// [rebuild]: super::callsite::rebuild_interest_cache
|
||||
fn max_level_hint(&self) -> Option<LevelFilter> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Visit the construction of a new span, returning a new [span ID] for the
|
||||
/// span being constructed.
|
||||
///
|
||||
/// The provided [`Attributes`] contains any field values that were provided
|
||||
/// when the span was created. The subscriber may pass a [visitor] to the
|
||||
/// `Attributes`' [`record` method] to record these values.
|
||||
///
|
||||
/// IDs are used to uniquely identify spans and events within the context of a
|
||||
/// subscriber, so span equality will be based on the returned ID. Thus, if
|
||||
/// the subscriber wishes for all spans with the same metadata to be
|
||||
/// considered equal, it should return the same ID every time it is given a
|
||||
/// particular set of metadata. Similarly, if it wishes for two separate
|
||||
/// instances of a span with the same metadata to *not* be equal, it should
|
||||
/// return a distinct ID every time this function is called, regardless of
|
||||
/// the metadata.
|
||||
///
|
||||
/// Note that the subscriber is free to assign span IDs based on whatever
|
||||
/// scheme it sees fit. Any guarantees about uniqueness, ordering, or ID
|
||||
/// reuse are left up to the subscriber implementation to determine.
|
||||
///
|
||||
/// [span ID]: super::span::Id
|
||||
/// [`Attributes`]: super::span::Attributes
|
||||
/// [visitor]: super::field::Visit
|
||||
/// [`record` method]: super::span::Attributes::record
|
||||
fn new_span(&self, span: &span::Attributes<'_>) -> span::Id;
|
||||
|
||||
// === Notification methods ===============================================
|
||||
|
||||
/// Record a set of values on a span.
|
||||
///
|
||||
/// This method will be invoked when value is recorded on a span.
|
||||
/// Recording multiple values for the same field is possible,
|
||||
/// but the actual behaviour is defined by the subscriber implementation.
|
||||
///
|
||||
/// Keep in mind that a span might not provide a value
|
||||
/// for each field it declares.
|
||||
///
|
||||
/// The subscriber is expected to provide a [visitor] to the `Record`'s
|
||||
/// [`record` method] in order to record the added values.
|
||||
///
|
||||
/// # Example
|
||||
/// "foo = 3" will be recorded when [`record`] is called on the
|
||||
/// `Attributes` passed to `new_span`.
|
||||
/// Since values are not provided for the `bar` and `baz` fields,
|
||||
/// the span's `Metadata` will indicate that it _has_ those fields,
|
||||
/// but values for them won't be recorded at this time.
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// # use tracing::span;
|
||||
///
|
||||
/// let mut span = span!("my_span", foo = 3, bar, baz);
|
||||
///
|
||||
/// // `Subscriber::record` will be called with a `Record`
|
||||
/// // containing "bar = false"
|
||||
/// span.record("bar", &false);
|
||||
///
|
||||
/// // `Subscriber::record` will be called with a `Record`
|
||||
/// // containing "baz = "a string""
|
||||
/// span.record("baz", &"a string");
|
||||
/// ```
|
||||
///
|
||||
/// [visitor]: super::field::Visit
|
||||
/// [`record`]: super::span::Attributes::record
|
||||
/// [`record` method]: super::span::Record::record
|
||||
fn record(&self, span: &span::Id, values: &span::Record<'_>);
|
||||
|
||||
/// Adds an indication that `span` follows from the span with the id
|
||||
/// `follows`.
|
||||
///
|
||||
/// This relationship differs somewhat from the parent-child relationship: a
|
||||
/// span may have any number of prior spans, rather than a single one; and
|
||||
/// spans are not considered to be executing _inside_ of the spans they
|
||||
/// follow from. This means that a span may close even if subsequent spans
|
||||
/// that follow from it are still open, and time spent inside of a
|
||||
/// subsequent span should not be included in the time its precedents were
|
||||
/// executing. This is used to model causal relationships such as when a
|
||||
/// single future spawns several related background tasks, et cetera.
|
||||
///
|
||||
/// If the subscriber has spans corresponding to the given IDs, it should
|
||||
/// record this relationship in whatever way it deems necessary. Otherwise,
|
||||
/// if one or both of the given span IDs do not correspond to spans that the
|
||||
/// subscriber knows about, or if a cyclical relationship would be created
|
||||
/// (i.e., some span _a_ which proceeds some other span _b_ may not also
|
||||
/// follow from _b_), it may silently do nothing.
|
||||
fn record_follows_from(&self, span: &span::Id, follows: &span::Id);
|
||||
|
||||
/// Records that an [`Event`] has occurred.
|
||||
///
|
||||
/// This method will be invoked when an Event is constructed by
|
||||
/// the `Event`'s [`dispatch` method]. For example, this happens internally
|
||||
/// when an event macro from `tracing` is called.
|
||||
///
|
||||
/// The key difference between this method and `record` is that `record` is
|
||||
/// called when a value is recorded for a field defined by a span,
|
||||
/// while `event` is called when a new event occurs.
|
||||
///
|
||||
/// The provided `Event` struct contains any field values attached to the
|
||||
/// event. The subscriber may pass a [visitor] to the `Event`'s
|
||||
/// [`record` method] to record these values.
|
||||
///
|
||||
/// [`Event`]: super::event::Event
|
||||
/// [visitor]: super::field::Visit
|
||||
/// [`record` method]: super::event::Event::record
|
||||
/// [`dispatch` method]: super::event::Event::dispatch
|
||||
fn event(&self, event: &Event<'_>);
|
||||
|
||||
/// Records that a span has been entered.
|
||||
///
|
||||
/// When entering a span, this method is called to notify the subscriber
|
||||
/// that the span has been entered. The subscriber is provided with the
|
||||
/// [span ID] of the entered span, and should update any internal state
|
||||
/// tracking the current span accordingly.
|
||||
///
|
||||
/// [span ID]: super::span::Id
|
||||
fn enter(&self, span: &span::Id);
|
||||
|
||||
/// Records that a span has been exited.
|
||||
///
|
||||
/// When exiting a span, this method is called to notify the subscriber
|
||||
/// that the span has been exited. The subscriber is provided with the
|
||||
/// [span ID] of the exited span, and should update any internal state
|
||||
/// tracking the current span accordingly.
|
||||
///
|
||||
/// Exiting a span does not imply that the span will not be re-entered.
|
||||
///
|
||||
/// [span ID]: super::span::Id
|
||||
fn exit(&self, span: &span::Id);
|
||||
|
||||
/// Notifies the subscriber that a [span ID] has been cloned.
|
||||
///
|
||||
/// This function is guaranteed to only be called with span IDs that were
|
||||
/// returned by this subscriber's `new_span` function.
|
||||
///
|
||||
/// Note that the default implementation of this function this is just the
|
||||
/// identity function, passing through the identifier. However, it can be
|
||||
/// used in conjunction with [`try_close`] to track the number of handles
|
||||
/// capable of `enter`ing a span. When all the handles have been dropped
|
||||
/// (i.e., `try_close` has been called one more time than `clone_span` for a
|
||||
/// given ID), the subscriber may assume that the span will not be entered
|
||||
/// again. It is then free to deallocate storage for data associated with
|
||||
/// that span, write data from that span to IO, and so on.
|
||||
///
|
||||
/// For more unsafe situations, however, if `id` is itself a pointer of some
|
||||
/// kind this can be used as a hook to "clone" the pointer, depending on
|
||||
/// what that means for the specified pointer.
|
||||
///
|
||||
/// [span ID]: super::span::Id
|
||||
/// [`try_close`]: Subscriber::try_close
|
||||
fn clone_span(&self, id: &span::Id) -> span::Id {
|
||||
id.clone()
|
||||
}
|
||||
|
||||
/// **This method is deprecated.**
|
||||
///
|
||||
/// Using `drop_span` may result in subscribers composed using
|
||||
/// `tracing-subscriber` crate's `Layer` trait from observing close events.
|
||||
/// Use [`try_close`] instead.
|
||||
///
|
||||
/// The default implementation of this function does nothing.
|
||||
///
|
||||
/// [`try_close`]: Subscriber::try_close
|
||||
#[deprecated(since = "0.1.2", note = "use `Subscriber::try_close` instead")]
|
||||
fn drop_span(&self, _id: span::Id) {}
|
||||
|
||||
/// Notifies the subscriber that a [span ID] has been dropped, and returns
|
||||
/// `true` if there are now 0 IDs that refer to that span.
|
||||
///
|
||||
/// Higher-level libraries providing functionality for composing multiple
|
||||
/// subscriber implementations may use this return value to notify any
|
||||
/// "layered" subscribers that this subscriber considers the span closed.
|
||||
///
|
||||
/// The default implementation of this method calls the subscriber's
|
||||
/// [`drop_span`] method and returns `false`. This means that, unless the
|
||||
/// subscriber overrides the default implementation, close notifications
|
||||
/// will never be sent to any layered subscribers. In general, if the
|
||||
/// subscriber tracks reference counts, this method should be implemented,
|
||||
/// rather than `drop_span`.
|
||||
///
|
||||
/// This function is guaranteed to only be called with span IDs that were
|
||||
/// returned by this subscriber's `new_span` function.
|
||||
///
|
||||
/// It's guaranteed that if this function has been called once more than the
|
||||
/// number of times `clone_span` was called with the same `id`, then no more
|
||||
/// handles that can enter the span with that `id` exist. This means that it
|
||||
/// can be used in conjunction with [`clone_span`] to track the number of
|
||||
/// handles capable of `enter`ing a span. When all the handles have been
|
||||
/// dropped (i.e., `try_close` has been called one more time than
|
||||
/// `clone_span` for a given ID), the subscriber may assume that the span
|
||||
/// will not be entered again, and should return `true`. It is then free to
|
||||
/// deallocate storage for data associated with that span, write data from
|
||||
/// that span to IO, and so on.
|
||||
///
|
||||
/// **Note**: since this function is called when spans are dropped,
|
||||
/// implementations should ensure that they are unwind-safe. Panicking from
|
||||
/// inside of a `try_close` function may cause a double panic, if the span
|
||||
/// was dropped due to a thread unwinding.
|
||||
///
|
||||
/// [span ID]: super::span::Id
|
||||
/// [`clone_span`]: Subscriber::clone_span
|
||||
/// [`drop_span`]: Subscriber::drop_span
|
||||
fn try_close(&self, id: span::Id) -> bool {
|
||||
#[allow(deprecated)]
|
||||
self.drop_span(id);
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns a type representing this subscriber's view of the current span.
|
||||
///
|
||||
/// If subscribers track a current span, they should override this function
|
||||
/// to return [`Current::new`] if the thread from which this method is
|
||||
/// called is inside a span, or [`Current::none`] if the thread is not
|
||||
/// inside a span.
|
||||
///
|
||||
/// By default, this returns a value indicating that the subscriber
|
||||
/// does **not** track what span is current. If the subscriber does not
|
||||
/// implement a current span, it should not override this method.
|
||||
///
|
||||
/// [`Current::new`]: super::span::Current#tymethod.new
|
||||
/// [`Current::none`]: super::span::Current#tymethod.none
|
||||
fn current_span(&self) -> span::Current {
|
||||
span::Current::unknown()
|
||||
}
|
||||
|
||||
// === Downcasting methods ================================================
|
||||
|
||||
/// If `self` is the same type as the provided `TypeId`, returns an untyped
|
||||
/// `*const` pointer to that type. Otherwise, returns `None`.
|
||||
///
|
||||
/// If you wish to downcast a `Subscriber`, it is strongly advised to use
|
||||
/// the safe API provided by [`downcast_ref`] instead.
|
||||
///
|
||||
/// This API is required for `downcast_raw` to be a trait method; a method
|
||||
/// signature like [`downcast_ref`] (with a generic type parameter) is not
|
||||
/// object-safe, and thus cannot be a trait method for `Subscriber`. This
|
||||
/// means that if we only exposed `downcast_ref`, `Subscriber`
|
||||
/// implementations could not override the downcasting behavior
|
||||
///
|
||||
/// This method may be overridden by "fan out" or "chained" subscriber
|
||||
/// implementations which consist of multiple composed types. Such
|
||||
/// subscribers might allow `downcast_raw` by returning references to those
|
||||
/// component if they contain components with the given `TypeId`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The [`downcast_ref`] method expects that the pointer returned by
|
||||
/// `downcast_raw` is non-null and points to a valid instance of the type
|
||||
/// with the provided `TypeId`. Failure to ensure this will result in
|
||||
/// undefined behaviour, so implementing `downcast_raw` is unsafe.
|
||||
///
|
||||
/// [`downcast_ref`]: #method.downcast_ref
|
||||
unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> {
|
||||
if id == TypeId::of::<Self>() {
|
||||
Some(self as *const Self as *const ())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn Subscriber {
|
||||
/// Returns `true` if this `Subscriber` is the same type as `T`.
|
||||
pub fn is<T: Any>(&self) -> bool {
|
||||
self.downcast_ref::<T>().is_some()
|
||||
}
|
||||
|
||||
/// Returns some reference to this `Subscriber` value if it is of type `T`,
|
||||
/// or `None` if it isn't.
|
||||
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
|
||||
unsafe {
|
||||
let raw = self.downcast_raw(TypeId::of::<T>())?;
|
||||
if raw.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(&*(raw as *const _))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates a [`Subscriber`]'s interest in a particular callsite.
|
||||
///
|
||||
/// `Subscriber`s return an `Interest` from their [`register_callsite`] methods
|
||||
/// in order to determine whether that span should be enabled or disabled.
|
||||
///
|
||||
/// [`Subscriber`]: super::Subscriber
|
||||
/// [`register_callsite`]: super::Subscriber::register_callsite
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Interest(InterestKind);
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
enum InterestKind {
|
||||
Never = 0,
|
||||
Sometimes = 1,
|
||||
Always = 2,
|
||||
}
|
||||
|
||||
impl Interest {
|
||||
/// Returns an `Interest` indicating that the subscriber is never interested
|
||||
/// in being notified about a callsite.
|
||||
///
|
||||
/// If all active subscribers are `never()` interested in a callsite, it will
|
||||
/// be completely disabled unless a new subscriber becomes active.
|
||||
#[inline]
|
||||
pub fn never() -> Self {
|
||||
Interest(InterestKind::Never)
|
||||
}
|
||||
|
||||
/// Returns an `Interest` indicating the subscriber is sometimes interested
|
||||
/// in being notified about a callsite.
|
||||
///
|
||||
/// If all active subscribers are `sometimes` or `never` interested in a
|
||||
/// callsite, the currently active subscriber will be asked to filter that
|
||||
/// callsite every time it creates a span. This will be the case until a new
|
||||
/// subscriber expresses that it is `always` interested in the callsite.
|
||||
#[inline]
|
||||
pub fn sometimes() -> Self {
|
||||
Interest(InterestKind::Sometimes)
|
||||
}
|
||||
|
||||
/// Returns an `Interest` indicating the subscriber is always interested in
|
||||
/// being notified about a callsite.
|
||||
///
|
||||
/// If any subscriber expresses that it is `always()` interested in a given
|
||||
/// callsite, then the callsite will always be enabled.
|
||||
#[inline]
|
||||
pub fn always() -> Self {
|
||||
Interest(InterestKind::Always)
|
||||
}
|
||||
|
||||
/// Returns `true` if the subscriber is never interested in being notified
|
||||
/// about this callsite.
|
||||
#[inline]
|
||||
pub fn is_never(&self) -> bool {
|
||||
matches!(self.0, InterestKind::Never)
|
||||
}
|
||||
|
||||
/// Returns `true` if the subscriber is sometimes interested in being notified
|
||||
/// about this callsite.
|
||||
#[inline]
|
||||
pub fn is_sometimes(&self) -> bool {
|
||||
matches!(self.0, InterestKind::Sometimes)
|
||||
}
|
||||
|
||||
/// Returns `true` if the subscriber is always interested in being notified
|
||||
/// about this callsite.
|
||||
#[inline]
|
||||
pub fn is_always(&self) -> bool {
|
||||
matches!(self.0, InterestKind::Always)
|
||||
}
|
||||
|
||||
/// Returns the common interest between these two Interests.
|
||||
///
|
||||
/// If both interests are the same, this propagates that interest.
|
||||
/// Otherwise, if they differ, the result must always be
|
||||
/// `Interest::sometimes` --- if the two subscribers differ in opinion, we
|
||||
/// will have to ask the current subscriber what it thinks, no matter what.
|
||||
pub(crate) fn and(self, rhs: Interest) -> Self {
|
||||
if self.0 == rhs.0 {
|
||||
self
|
||||
} else {
|
||||
Interest::sometimes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A no-op [`Subscriber`].
|
||||
///
|
||||
/// [`NoSubscriber`] implements the [`Subscriber`] trait by never being enabled,
|
||||
/// never being interested in any callsite, and dropping all spans and events.
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
pub struct NoSubscriber(());
|
||||
|
||||
impl Subscriber for NoSubscriber {
|
||||
#[inline]
|
||||
fn register_callsite(&self, _: &'static Metadata<'static>) -> Interest {
|
||||
Interest::never()
|
||||
}
|
||||
|
||||
fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
|
||||
span::Id::from_u64(0xDEAD)
|
||||
}
|
||||
|
||||
fn event(&self, _event: &Event<'_>) {}
|
||||
|
||||
fn record(&self, _span: &span::Id, _values: &span::Record<'_>) {}
|
||||
|
||||
fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}
|
||||
|
||||
#[inline]
|
||||
fn enabled(&self, _metadata: &Metadata<'_>) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn enter(&self, _span: &span::Id) {}
|
||||
fn exit(&self, _span: &span::Id) {}
|
||||
}
|
||||
|
||||
impl Subscriber for Box<dyn Subscriber + Send + Sync + 'static> {
|
||||
#[inline]
|
||||
fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
|
||||
self.as_ref().register_callsite(metadata)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn enabled(&self, metadata: &Metadata<'_>) -> bool {
|
||||
self.as_ref().enabled(metadata)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max_level_hint(&self) -> Option<LevelFilter> {
|
||||
self.as_ref().max_level_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn new_span(&self, span: &span::Attributes<'_>) -> span::Id {
|
||||
self.as_ref().new_span(span)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn record(&self, span: &span::Id, values: &span::Record<'_>) {
|
||||
self.as_ref().record(span, values)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn record_follows_from(&self, span: &span::Id, follows: &span::Id) {
|
||||
self.as_ref().record_follows_from(span, follows)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn event(&self, event: &Event<'_>) {
|
||||
self.as_ref().event(event)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn enter(&self, span: &span::Id) {
|
||||
self.as_ref().enter(span)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn exit(&self, span: &span::Id) {
|
||||
self.as_ref().exit(span)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn clone_span(&self, id: &span::Id) -> span::Id {
|
||||
self.as_ref().clone_span(id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_close(&self, id: span::Id) -> bool {
|
||||
self.as_ref().try_close(id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(deprecated)]
|
||||
fn drop_span(&self, id: span::Id) {
|
||||
self.as_ref().try_close(id);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn current_span(&self) -> span::Current {
|
||||
self.as_ref().current_span()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> {
|
||||
if id == TypeId::of::<Self>() {
|
||||
return Some(self as *const Self as *const _);
|
||||
}
|
||||
|
||||
self.as_ref().downcast_raw(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl Subscriber for Arc<dyn Subscriber + Send + Sync + 'static> {
|
||||
#[inline]
|
||||
fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
|
||||
self.as_ref().register_callsite(metadata)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn enabled(&self, metadata: &Metadata<'_>) -> bool {
|
||||
self.as_ref().enabled(metadata)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max_level_hint(&self) -> Option<LevelFilter> {
|
||||
self.as_ref().max_level_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn new_span(&self, span: &span::Attributes<'_>) -> span::Id {
|
||||
self.as_ref().new_span(span)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn record(&self, span: &span::Id, values: &span::Record<'_>) {
|
||||
self.as_ref().record(span, values)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn record_follows_from(&self, span: &span::Id, follows: &span::Id) {
|
||||
self.as_ref().record_follows_from(span, follows)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn event(&self, event: &Event<'_>) {
|
||||
self.as_ref().event(event)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn enter(&self, span: &span::Id) {
|
||||
self.as_ref().enter(span)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn exit(&self, span: &span::Id) {
|
||||
self.as_ref().exit(span)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn clone_span(&self, id: &span::Id) -> span::Id {
|
||||
self.as_ref().clone_span(id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_close(&self, id: span::Id) -> bool {
|
||||
self.as_ref().try_close(id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(deprecated)]
|
||||
fn drop_span(&self, id: span::Id) {
|
||||
self.as_ref().try_close(id);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn current_span(&self) -> span::Current {
|
||||
self.as_ref().current_span()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> {
|
||||
if id == TypeId::of::<Self>() {
|
||||
return Some(self as *const Self as *const _);
|
||||
}
|
||||
|
||||
self.as_ref().downcast_raw(id)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user