]> git.proxmox.com Git - rustc.git/blob - vendor/tracing-subscriber-0.3.3/src/registry/mod.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / vendor / tracing-subscriber-0.3.3 / src / registry / mod.rs
1 //! Storage for span data shared by multiple [`Layer`]s.
2 //!
3 //! ## Using the Span Registry
4 //!
5 //! This module provides the [`Registry`] type, a [`Subscriber`] implementation
6 //! which tracks per-span data and exposes it to [`Layer`]s. When a `Registry`
7 //! is used as the base `Subscriber` of a `Layer` stack, the
8 //! [`layer::Context`][ctx] type will provide methods allowing `Layer`s to
9 //! [look up span data][lookup] stored in the registry. While [`Registry`] is a
10 //! reasonable default for storing spans and events, other stores that implement
11 //! [`LookupSpan`] and [`Subscriber`] themselves (with [`SpanData`] implemented
12 //! by the per-span data they store) can be used as a drop-in replacement.
13 //!
14 //! For example, we might create a `Registry` and add multiple `Layer`s like so:
15 //! ```rust
16 //! use tracing_subscriber::{registry::Registry, Layer, prelude::*};
17 //! # use tracing_core::Subscriber;
18 //! # pub struct FooLayer {}
19 //! # pub struct BarLayer {}
20 //! # impl<S: Subscriber> Layer<S> for FooLayer {}
21 //! # impl<S: Subscriber> Layer<S> for BarLayer {}
22 //! # impl FooLayer {
23 //! # fn new() -> Self { Self {} }
24 //! # }
25 //! # impl BarLayer {
26 //! # fn new() -> Self { Self {} }
27 //! # }
28 //!
29 //! let subscriber = Registry::default()
30 //! .with(FooLayer::new())
31 //! .with(BarLayer::new());
32 //! ```
33 //!
34 //! If a type implementing `Layer` depends on the functionality of a `Registry`
35 //! implementation, it should bound its `Subscriber` type parameter with the
36 //! [`LookupSpan`] trait, like so:
37 //!
38 //! ```rust
39 //! use tracing_subscriber::{registry, Layer};
40 //! use tracing_core::Subscriber;
41 //!
42 //! pub struct MyLayer {
43 //! // ...
44 //! }
45 //!
46 //! impl<S> Layer<S> for MyLayer
47 //! where
48 //! S: Subscriber + for<'a> registry::LookupSpan<'a>,
49 //! {
50 //! // ...
51 //! }
52 //! ```
53 //! When this bound is added, the `Layer` implementation will be guaranteed
54 //! access to the [`Context`][ctx] methods, such as [`Context::span`][lookup], that
55 //! require the root subscriber to be a registry.
56 //!
57 //! [`Layer`]: crate::layer::Layer
58 //! [`Subscriber`]:
59 //! https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html
60 //! [ctx]: crate::layer::Context
61 //! [lookup]: crate::layer::Context::span()
62 use tracing_core::{field::FieldSet, span::Id, Metadata};
63
64 feature! {
65 #![feature = "std"]
66 /// A module containing a type map of span extensions.
67 mod extensions;
68 pub use extensions::{Extensions, ExtensionsMut};
69
70 }
71
72 feature! {
73 #![all(feature = "registry", feature = "std")]
74
75 mod sharded;
76 mod stack;
77
78 pub use sharded::Data;
79 pub use sharded::Registry;
80
81 use crate::filter::FilterId;
82 }
83
84 /// Provides access to stored span data.
85 ///
86 /// Subscribers which store span data and associate it with span IDs should
87 /// implement this trait; if they do, any [`Layer`]s wrapping them can look up
88 /// metadata via the [`Context`] type's [`span()`] method.
89 ///
90 /// [`Layer`]: ../layer/trait.Layer.html
91 /// [`Context`]: ../layer/struct.Context.html
92 /// [`span()`]: ../layer/struct.Context.html#method.span
93 pub trait LookupSpan<'a> {
94 /// The type of span data stored in this registry.
95 type Data: SpanData<'a>;
96
97 /// Returns the [`SpanData`] for a given `Id`, if it exists.
98 ///
99 /// <pre class="ignore" style="white-space:normal;font:inherit;">
100 /// <strong>Note</strong>: users of the <code>LookupSpan</code> trait should
101 /// typically call the <a href="#method.span"><code>span</code></a> method rather
102 /// than this method. The <code>span</code> method is implemented by
103 /// <em>calling</em> <code>span_data</code>, but returns a reference which is
104 /// capable of performing more sophisiticated queries.
105 /// </pre>
106 ///
107 /// [`SpanData`]: trait.SpanData.html
108 fn span_data(&'a self, id: &Id) -> Option<Self::Data>;
109
110 /// Returns a [`SpanRef`] for the span with the given `Id`, if it exists.
111 ///
112 /// A `SpanRef` is similar to [`SpanData`], but it allows performing
113 /// additional lookups against the registryr that stores the wrapped data.
114 ///
115 /// In general, _users_ of the `LookupSpan` trait should use this method
116 /// rather than the [`span_data`] method; while _implementors_ of this trait
117 /// should only implement `span_data`.
118 ///
119 /// [`SpanRef`]: struct.SpanRef.html
120 /// [`SpanData`]: trait.SpanData.html
121 /// [`span_data`]: #method.span_data
122 fn span(&'a self, id: &Id) -> Option<SpanRef<'_, Self>>
123 where
124 Self: Sized,
125 {
126 let data = self.span_data(id)?;
127 Some(SpanRef {
128 registry: self,
129 data,
130 #[cfg(feature = "registry")]
131 filter: FilterId::none(),
132 })
133 }
134
135 /// Registers a [`Filter`] for [per-layer filtering] with this
136 /// [`Subscriber`].
137 ///
138 /// The [`Filter`] can then use the returned [`FilterId`] to
139 /// [check if it previously enabled a span][check].
140 ///
141 /// # Panics
142 ///
143 /// If this `Subscriber` does not support [per-layer filtering].
144 ///
145 /// [`Filter`]: crate::layer::Filter
146 /// [per-layer filtering]: crate::layer::Layer#per-layer-filtering
147 /// [`Subscriber`]: tracing_core::Subscriber
148 /// [`FilterId`]: crate::filter::FilterId
149 /// [check]: SpanData::is_enabled_for
150 #[cfg(feature = "registry")]
151 #[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
152 fn register_filter(&mut self) -> FilterId {
153 panic!(
154 "{} does not currently support filters",
155 std::any::type_name::<Self>()
156 )
157 }
158 }
159
160 /// A stored representation of data associated with a span.
161 pub trait SpanData<'a> {
162 /// Returns this span's ID.
163 fn id(&self) -> Id;
164
165 /// Returns a reference to the span's `Metadata`.
166 fn metadata(&self) -> &'static Metadata<'static>;
167
168 /// Returns a reference to the ID
169 fn parent(&self) -> Option<&Id>;
170
171 /// Returns a reference to this span's `Extensions`.
172 ///
173 /// The extensions may be used by `Layer`s to store additional data
174 /// describing the span.
175 #[cfg(feature = "std")]
176 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
177 fn extensions(&self) -> Extensions<'_>;
178
179 /// Returns a mutable reference to this span's `Extensions`.
180 ///
181 /// The extensions may be used by `Layer`s to store additional data
182 /// describing the span.
183 #[cfg(feature = "std")]
184 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
185 fn extensions_mut(&self) -> ExtensionsMut<'_>;
186
187 /// Returns `true` if this span is enabled for the [per-layer filter][plf]
188 /// corresponding to the provided [`FilterId`].
189 ///
190 /// ## Default Implementation
191 ///
192 /// By default, this method assumes that the [`LookupSpan`] implementation
193 /// does not support [per-layer filtering][plf], and always returns `true`.
194 ///
195 /// [plf]: crate::layer::Layer#per-layer-filtering
196 /// [`FilterId`]: crate::filter::FilterId
197 #[cfg(feature = "registry")]
198 #[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
199 fn is_enabled_for(&self, filter: FilterId) -> bool {
200 let _ = filter;
201 true
202 }
203 }
204
205 /// A reference to [span data] and the associated [registry].
206 ///
207 /// This type implements all the same methods as [`SpanData`][span data], and
208 /// provides additional methods for querying the registry based on values from
209 /// the span.
210 ///
211 /// [span data]: trait.SpanData.html
212 /// [registry]: trait.LookupSpan.html
213 #[derive(Debug)]
214 pub struct SpanRef<'a, R: LookupSpan<'a>> {
215 registry: &'a R,
216 data: R::Data,
217
218 #[cfg(feature = "registry")]
219 filter: FilterId,
220 }
221
222 /// An iterator over the parents of a span, ordered from leaf to root.
223 ///
224 /// This is returned by the [`SpanRef::scope`] method.
225 #[derive(Debug)]
226 pub struct Scope<'a, R> {
227 registry: &'a R,
228 next: Option<Id>,
229
230 #[cfg(all(feature = "registry", feature = "std"))]
231 filter: FilterId,
232 }
233
234 feature! {
235 #![any(feature = "alloc", feature = "std")]
236
237 #[cfg(not(feature = "smallvec"))]
238 use alloc::vec::{self, Vec};
239
240 use core::{fmt,iter};
241
242 /// An iterator over the parents of a span, ordered from root to leaf.
243 ///
244 /// This is returned by the [`Scope::from_root`] method.
245 pub struct ScopeFromRoot<'a, R>
246 where
247 R: LookupSpan<'a>,
248 {
249 #[cfg(feature = "smallvec")]
250 spans: iter::Rev<smallvec::IntoIter<SpanRefVecArray<'a, R>>>,
251 #[cfg(not(feature = "smallvec"))]
252 spans: iter::Rev<vec::IntoIter<SpanRef<'a, R>>>,
253 }
254
255 #[cfg(feature = "smallvec")]
256 type SpanRefVecArray<'span, L> = [SpanRef<'span, L>; 16];
257
258 impl<'a, R> Scope<'a, R>
259 where
260 R: LookupSpan<'a>,
261 {
262 /// Flips the order of the iterator, so that it is ordered from root to leaf.
263 ///
264 /// The iterator will first return the root span, then that span's immediate child,
265 /// and so on until it finally returns the span that [`SpanRef::scope`] was called on.
266 ///
267 /// If any items were consumed from the [`Scope`] before calling this method then they
268 /// will *not* be returned from the [`ScopeFromRoot`].
269 ///
270 /// **Note**: this will allocate if there are many spans remaining, or if the
271 /// "smallvec" feature flag is not enabled.
272 #[allow(clippy::wrong_self_convention)]
273 pub fn from_root(self) -> ScopeFromRoot<'a, R> {
274 #[cfg(feature = "smallvec")]
275 type Buf<T> = smallvec::SmallVec<T>;
276 #[cfg(not(feature = "smallvec"))]
277 type Buf<T> = Vec<T>;
278 ScopeFromRoot {
279 spans: self.collect::<Buf<_>>().into_iter().rev(),
280 }
281 }
282 }
283
284 impl<'a, R> Iterator for ScopeFromRoot<'a, R>
285 where
286 R: LookupSpan<'a>,
287 {
288 type Item = SpanRef<'a, R>;
289
290 #[inline]
291 fn next(&mut self) -> Option<Self::Item> {
292 self.spans.next()
293 }
294
295 #[inline]
296 fn size_hint(&self) -> (usize, Option<usize>) {
297 self.spans.size_hint()
298 }
299 }
300
301 impl<'a, R> fmt::Debug for ScopeFromRoot<'a, R>
302 where
303 R: LookupSpan<'a>,
304 {
305 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
306 f.pad("ScopeFromRoot { .. }")
307 }
308 }
309 }
310
311 impl<'a, R> Iterator for Scope<'a, R>
312 where
313 R: LookupSpan<'a>,
314 {
315 type Item = SpanRef<'a, R>;
316
317 fn next(&mut self) -> Option<Self::Item> {
318 loop {
319 let curr = self.registry.span(self.next.as_ref()?)?;
320
321 #[cfg(all(feature = "registry", feature = "std"))]
322 let curr = curr.with_filter(self.filter);
323 self.next = curr.data.parent().cloned();
324
325 // If the `Scope` is filtered, check if the current span is enabled
326 // by the selected filter ID.
327
328 #[cfg(all(feature = "registry", feature = "std"))]
329 {
330 if !curr.is_enabled_for(self.filter) {
331 // The current span in the chain is disabled for this
332 // filter. Try its parent.
333 continue;
334 }
335 }
336
337 return Some(curr);
338 }
339 }
340 }
341
342 impl<'a, R> SpanRef<'a, R>
343 where
344 R: LookupSpan<'a>,
345 {
346 /// Returns this span's ID.
347 pub fn id(&self) -> Id {
348 self.data.id()
349 }
350
351 /// Returns a static reference to the span's metadata.
352 pub fn metadata(&self) -> &'static Metadata<'static> {
353 self.data.metadata()
354 }
355
356 /// Returns the span's name,
357 pub fn name(&self) -> &'static str {
358 self.data.metadata().name()
359 }
360
361 /// Returns a list of [fields] defined by the span.
362 ///
363 /// [fields]: https://docs.rs/tracing-core/latest/tracing_core/field/index.html
364 pub fn fields(&self) -> &FieldSet {
365 self.data.metadata().fields()
366 }
367
368 /// Returns a `SpanRef` describing this span's parent, or `None` if this
369 /// span is the root of its trace tree.
370 pub fn parent(&self) -> Option<Self> {
371 let id = self.data.parent()?;
372 let data = self.registry.span_data(id)?;
373
374 #[cfg(all(feature = "registry", feature = "std"))]
375 {
376 // move these into mut bindings if the registry feature is enabled,
377 // since they may be mutated in the loop.
378 let mut data = data;
379 loop {
380 // Is this parent enabled by our filter?
381 if data.is_enabled_for(self.filter) {
382 return Some(Self {
383 registry: self.registry,
384 filter: self.filter,
385 data,
386 });
387 }
388
389 // It's not enabled. If the disabled span has a parent, try that!
390 let id = data.parent()?;
391 data = self.registry.span_data(id)?;
392 }
393 }
394
395 #[cfg(not(all(feature = "registry", feature = "std")))]
396 Some(Self {
397 registry: self.registry,
398 data,
399 })
400 }
401
402 /// Returns an iterator over all parents of this span, starting with this span,
403 /// ordered from leaf to root.
404 ///
405 /// The iterator will first return the span, then the span's immediate parent,
406 /// followed by that span's parent, and so on, until it reaches a root span.
407 ///
408 /// ```rust
409 /// use tracing::{span, Subscriber};
410 /// use tracing_subscriber::{
411 /// layer::{Context, Layer},
412 /// prelude::*,
413 /// registry::LookupSpan,
414 /// };
415 ///
416 /// struct PrintingLayer;
417 /// impl<S> Layer<S> for PrintingLayer
418 /// where
419 /// S: Subscriber + for<'lookup> LookupSpan<'lookup>,
420 /// {
421 /// fn on_enter(&self, id: &span::Id, ctx: Context<S>) {
422 /// let span = ctx.span(id).unwrap();
423 /// let scope = span.scope().map(|span| span.name()).collect::<Vec<_>>();
424 /// println!("Entering span: {:?}", scope);
425 /// }
426 /// }
427 ///
428 /// tracing::subscriber::with_default(tracing_subscriber::registry().with(PrintingLayer), || {
429 /// let _root = tracing::info_span!("root").entered();
430 /// // Prints: Entering span: ["root"]
431 /// let _child = tracing::info_span!("child").entered();
432 /// // Prints: Entering span: ["child", "root"]
433 /// let _leaf = tracing::info_span!("leaf").entered();
434 /// // Prints: Entering span: ["leaf", "child", "root"]
435 /// });
436 /// ```
437 ///
438 /// If the opposite order (from the root to this span) is desired, calling [`Scope::from_root`] on
439 /// the returned iterator reverses the order.
440 ///
441 /// ```rust
442 /// # use tracing::{span, Subscriber};
443 /// # use tracing_subscriber::{
444 /// # layer::{Context, Layer},
445 /// # prelude::*,
446 /// # registry::LookupSpan,
447 /// # };
448 /// # struct PrintingLayer;
449 /// impl<S> Layer<S> for PrintingLayer
450 /// where
451 /// S: Subscriber + for<'lookup> LookupSpan<'lookup>,
452 /// {
453 /// fn on_enter(&self, id: &span::Id, ctx: Context<S>) {
454 /// let span = ctx.span(id).unwrap();
455 /// let scope = span.scope().from_root().map(|span| span.name()).collect::<Vec<_>>();
456 /// println!("Entering span: {:?}", scope);
457 /// }
458 /// }
459 ///
460 /// tracing::subscriber::with_default(tracing_subscriber::registry().with(PrintingLayer), || {
461 /// let _root = tracing::info_span!("root").entered();
462 /// // Prints: Entering span: ["root"]
463 /// let _child = tracing::info_span!("child").entered();
464 /// // Prints: Entering span: ["root", "child"]
465 /// let _leaf = tracing::info_span!("leaf").entered();
466 /// // Prints: Entering span: ["root", "child", "leaf"]
467 /// });
468 /// ```
469 pub fn scope(&self) -> Scope<'a, R> {
470 Scope {
471 registry: self.registry,
472 next: Some(self.id()),
473
474 #[cfg(feature = "registry")]
475 filter: self.filter,
476 }
477 }
478
479 /// Returns a reference to this span's `Extensions`.
480 ///
481 /// The extensions may be used by `Layer`s to store additional data
482 /// describing the span.
483 #[cfg(feature = "std")]
484 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
485 pub fn extensions(&self) -> Extensions<'_> {
486 self.data.extensions()
487 }
488
489 /// Returns a mutable reference to this span's `Extensions`.
490 ///
491 /// The extensions may be used by `Layer`s to store additional data
492 /// describing the span.
493 #[cfg(feature = "std")]
494 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
495 pub fn extensions_mut(&self) -> ExtensionsMut<'_> {
496 self.data.extensions_mut()
497 }
498
499 #[cfg(all(feature = "registry", feature = "std"))]
500 pub(crate) fn try_with_filter(self, filter: FilterId) -> Option<Self> {
501 if self.is_enabled_for(filter) {
502 return Some(self.with_filter(filter));
503 }
504
505 None
506 }
507
508 #[inline]
509 #[cfg(all(feature = "registry", feature = "std"))]
510 pub(crate) fn is_enabled_for(&self, filter: FilterId) -> bool {
511 self.data.is_enabled_for(filter)
512 }
513
514 #[inline]
515 #[cfg(all(feature = "registry", feature = "std"))]
516 fn with_filter(self, filter: FilterId) -> Self {
517 Self { filter, ..self }
518 }
519 }
520
521 #[cfg(all(test, feature = "registry", feature = "std"))]
522 mod tests {
523 use crate::{
524 layer::{Context, Layer},
525 prelude::*,
526 registry::LookupSpan,
527 };
528 use std::sync::{Arc, Mutex};
529 use tracing::{span, Subscriber};
530
531 #[test]
532 fn spanref_scope_iteration_order() {
533 let last_entered_scope = Arc::new(Mutex::new(Vec::new()));
534
535 #[derive(Default)]
536 struct PrintingLayer {
537 last_entered_scope: Arc<Mutex<Vec<&'static str>>>,
538 }
539
540 impl<S> Layer<S> for PrintingLayer
541 where
542 S: Subscriber + for<'lookup> LookupSpan<'lookup>,
543 {
544 fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
545 let span = ctx.span(id).unwrap();
546 let scope = span.scope().map(|span| span.name()).collect::<Vec<_>>();
547 *self.last_entered_scope.lock().unwrap() = scope;
548 }
549 }
550
551 let _guard = tracing::subscriber::set_default(crate::registry().with(PrintingLayer {
552 last_entered_scope: last_entered_scope.clone(),
553 }));
554
555 let _root = tracing::info_span!("root").entered();
556 assert_eq!(&*last_entered_scope.lock().unwrap(), &["root"]);
557 let _child = tracing::info_span!("child").entered();
558 assert_eq!(&*last_entered_scope.lock().unwrap(), &["child", "root"]);
559 let _leaf = tracing::info_span!("leaf").entered();
560 assert_eq!(
561 &*last_entered_scope.lock().unwrap(),
562 &["leaf", "child", "root"]
563 );
564 }
565
566 #[test]
567 fn spanref_scope_fromroot_iteration_order() {
568 let last_entered_scope = Arc::new(Mutex::new(Vec::new()));
569
570 #[derive(Default)]
571 struct PrintingLayer {
572 last_entered_scope: Arc<Mutex<Vec<&'static str>>>,
573 }
574
575 impl<S> Layer<S> for PrintingLayer
576 where
577 S: Subscriber + for<'lookup> LookupSpan<'lookup>,
578 {
579 fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
580 let span = ctx.span(id).unwrap();
581 let scope = span
582 .scope()
583 .from_root()
584 .map(|span| span.name())
585 .collect::<Vec<_>>();
586 *self.last_entered_scope.lock().unwrap() = scope;
587 }
588 }
589
590 let _guard = tracing::subscriber::set_default(crate::registry().with(PrintingLayer {
591 last_entered_scope: last_entered_scope.clone(),
592 }));
593
594 let _root = tracing::info_span!("root").entered();
595 assert_eq!(&*last_entered_scope.lock().unwrap(), &["root"]);
596 let _child = tracing::info_span!("child").entered();
597 assert_eq!(&*last_entered_scope.lock().unwrap(), &["root", "child",]);
598 let _leaf = tracing::info_span!("leaf").entered();
599 assert_eq!(
600 &*last_entered_scope.lock().unwrap(),
601 &["root", "child", "leaf"]
602 );
603 }
604 }