]> git.proxmox.com Git - rustc.git/blame - vendor/tracing-core/src/callsite.rs
New upstream version 1.62.1+dfsg1
[rustc.git] / vendor / tracing-core / src / callsite.rs
CommitLineData
f035d41b
XL
1//! Callsites represent the source locations from which spans or events
2//! originate.
3use crate::stdlib::{
4 fmt,
5 hash::{Hash, Hasher},
f035d41b
XL
6 sync::Mutex,
7 vec::Vec,
8};
9use crate::{
3dfed10e
XL
10 dispatcher::{self, Dispatch},
11 metadata::{LevelFilter, Metadata},
f035d41b 12 subscriber::Interest,
f035d41b
XL
13};
14
5099ac24 15crate::lazy_static! {
f035d41b
XL
16 static ref REGISTRY: Mutex<Registry> = Mutex::new(Registry {
17 callsites: Vec::new(),
18 dispatchers: Vec::new(),
19 });
20}
21
22struct Registry {
23 callsites: Vec<&'static dyn Callsite>,
24 dispatchers: Vec<dispatcher::Registrar>,
25}
26
27impl Registry {
28 fn rebuild_callsite_interest(&self, callsite: &'static dyn Callsite) {
29 let meta = callsite.metadata();
30
1b1a35ee
XL
31 // Iterate over the subscribers in the registry, and — if they are
32 // active — register the callsite with them.
33 let mut interests = self
34 .dispatchers
35 .iter()
36 .filter_map(|registrar| registrar.try_register(meta));
f035d41b 37
1b1a35ee
XL
38 // Use the first subscriber's `Interest` as the base value.
39 let interest = if let Some(interest) = interests.next() {
40 // Combine all remaining `Interest`s.
41 interests.fold(interest, Interest::and)
42 } else {
43 // If nobody was interested in this thing, just return `never`.
44 Interest::never()
45 };
f035d41b
XL
46
47 callsite.set_interest(interest)
48 }
49
50 fn rebuild_interest(&mut self) {
3dfed10e
XL
51 let mut max_level = LevelFilter::OFF;
52 self.dispatchers.retain(|registrar| {
53 if let Some(dispatch) = registrar.upgrade() {
54 // If the subscriber did not provide a max level hint, assume
55 // that it may enable every level.
56 let level_hint = dispatch.max_level_hint().unwrap_or(LevelFilter::TRACE);
57 if level_hint > max_level {
58 max_level = level_hint;
59 }
60 true
61 } else {
62 false
63 }
64 });
f035d41b
XL
65
66 self.callsites.iter().for_each(|&callsite| {
67 self.rebuild_callsite_interest(callsite);
68 });
3dfed10e 69 LevelFilter::set_max(max_level);
f035d41b
XL
70 }
71}
72
73/// Trait implemented by callsites.
74///
29967ef6 75/// These functions are only intended to be called by the callsite registry, which
f035d41b
XL
76/// correctly handles determining the common interest between all subscribers.
77pub trait Callsite: Sync {
78 /// Sets the [`Interest`] for this callsite.
79 ///
04454e1e 80 /// [`Interest`]: super::subscriber::Interest
f035d41b
XL
81 fn set_interest(&self, interest: Interest);
82
83 /// Returns the [metadata] associated with the callsite.
84 ///
04454e1e 85 /// [metadata]: super::metadata::Metadata
f035d41b
XL
86 fn metadata(&self) -> &Metadata<'_>;
87}
88
89/// Uniquely identifies a [`Callsite`]
90///
91/// Two `Identifier`s are equal if they both refer to the same callsite.
92///
04454e1e 93/// [`Callsite`]: super::callsite::Callsite
f035d41b
XL
94#[derive(Clone)]
95pub struct Identifier(
96 /// **Warning**: The fields on this type are currently `pub` because it must
97 /// be able to be constructed statically by macros. However, when `const
98 /// fn`s are available on stable Rust, this will no longer be necessary.
99 /// Thus, these fields are *not* considered stable public API, and they may
100 /// change warning. Do not rely on any fields on `Identifier`. When
04454e1e
FG
101 /// constructing new `Identifier`s, use the `identify_callsite!` macro
102 /// instead.
f035d41b
XL
103 #[doc(hidden)]
104 pub &'static dyn Callsite,
105);
106
107/// Clear and reregister interest on every [`Callsite`]
108///
109/// This function is intended for runtime reconfiguration of filters on traces
110/// when the filter recalculation is much less frequent than trace events are.
111/// The alternative is to have the [`Subscriber`] that supports runtime
112/// reconfiguration of filters always return [`Interest::sometimes()`] so that
113/// [`enabled`] is evaluated for every event.
114///
3dfed10e 115/// This function will also re-compute the global maximum level as determined by
29967ef6 116/// the [`max_level_hint`] method. If a [`Subscriber`]
3dfed10e
XL
117/// implementation changes the value returned by its `max_level_hint`
118/// implementation at runtime, then it **must** call this function after that
119/// value changes, in order for the change to be reflected.
120///
04454e1e
FG
121/// [`max_level_hint`]: super::subscriber::Subscriber::max_level_hint
122/// [`Callsite`]: super::callsite::Callsite
123/// [`enabled`]: super::subscriber::Subscriber#tymethod.enabled
124/// [`Interest::sometimes()`]: super::subscriber::Interest::sometimes
125/// [`Subscriber`]: super::subscriber::Subscriber
f035d41b
XL
126pub fn rebuild_interest_cache() {
127 let mut registry = REGISTRY.lock().unwrap();
128 registry.rebuild_interest();
129}
130
131/// Register a new `Callsite` with the global registry.
132///
133/// This should be called once per callsite after the callsite has been
134/// constructed.
135pub fn register(callsite: &'static dyn Callsite) {
136 let mut registry = REGISTRY.lock().unwrap();
137 registry.rebuild_callsite_interest(callsite);
138 registry.callsites.push(callsite);
139}
140
141pub(crate) fn register_dispatch(dispatch: &Dispatch) {
142 let mut registry = REGISTRY.lock().unwrap();
143 registry.dispatchers.push(dispatch.registrar());
144 registry.rebuild_interest();
145}
146
147// ===== impl Identifier =====
148
149impl PartialEq for Identifier {
150 fn eq(&self, other: &Identifier) -> bool {
17df50a5
XL
151 core::ptr::eq(
152 self.0 as *const _ as *const (),
153 other.0 as *const _ as *const (),
154 )
f035d41b
XL
155 }
156}
157
158impl Eq for Identifier {}
159
160impl fmt::Debug for Identifier {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 write!(f, "Identifier({:p})", self.0)
163 }
164}
165
166impl Hash for Identifier {
167 fn hash<H>(&self, state: &mut H)
168 where
169 H: Hasher,
170 {
171 (self.0 as *const dyn Callsite).hash(state)
172 }
173}