1use sharded_slab::{pool::Ref, Clear, Pool};
2use thread_local::ThreadLocal;
3
4use super::stack::SpanStack;
5use crate::{
6 filter::{FilterId, FilterMap, FilterState},
7 registry::{
8 extensions::{Extensions, ExtensionsInner, ExtensionsMut},
9 LookupSpan, SpanData,
10 },
11 sync::RwLock,
12};
13use core::{
14 cell::{self, Cell, RefCell},
15 sync::atomic::{fence, AtomicUsize, Ordering},
16};
17use std::thread_local;
18use tracing_core::{
19 dispatcher::{self, Dispatch},
20 span::{self, Current, Id},
21 Event, Interest, Metadata, Subscriber,
22};
23
24#[cfg(feature = "registry")]
91#[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))]
92#[derive(Debug)]
93pub struct Registry {
94 spans: Pool<DataInner>,
95 current_spans: ThreadLocal<RefCell<SpanStack>>,
96 next_filter_id: u8,
97}
98
99#[cfg(feature = "registry")]
109#[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))]
110#[derive(Debug)]
111pub struct Data<'a> {
112 inner: Ref<'a, DataInner>,
114}
115
116#[derive(Debug)]
124struct DataInner {
125 filter_map: FilterMap,
126 metadata: &'static Metadata<'static>,
127 parent: Option<Id>,
128 ref_count: AtomicUsize,
129 pub(crate) extensions: RwLock<ExtensionsInner>,
132}
133
134impl Default for Registry {
137 fn default() -> Self {
138 Self {
139 spans: Pool::new(),
140 current_spans: ThreadLocal::new(),
141 next_filter_id: 0,
142 }
143 }
144}
145
146#[inline]
147fn idx_to_id(idx: usize) -> Id {
148 Id::from_u64(idx as u64 + 1)
149}
150
151#[inline]
152fn id_to_idx(id: &Id) -> usize {
153 id.into_u64() as usize - 1
154}
155
156pub(crate) struct CloseGuard<'a> {
178 id: Id,
179 registry: &'a Registry,
180 is_closing: bool,
181}
182
183impl Registry {
184 fn get(&self, id: &Id) -> Option<Ref<'_, DataInner>> {
185 self.spans.get(id_to_idx(id))
186 }
187
188 pub(crate) fn start_close(&self, id: Id) -> CloseGuard<'_> {
193 CLOSE_COUNT.with(|count| {
194 let c = count.get();
195 count.set(c + 1);
196 });
197 CloseGuard {
198 id,
199 registry: self,
200 is_closing: false,
201 }
202 }
203
204 pub(crate) fn has_per_layer_filters(&self) -> bool {
205 self.next_filter_id > 0
206 }
207
208 pub(crate) fn span_stack(&self) -> cell::Ref<'_, SpanStack> {
209 self.current_spans.get_or_default().borrow()
210 }
211}
212
213thread_local! {
214 static CLOSE_COUNT: Cell<usize> = const { Cell::new(0) };
219}
220
221impl Subscriber for Registry {
222 fn register_callsite(&self, _: &'static Metadata<'static>) -> Interest {
223 if self.has_per_layer_filters() {
224 return FilterState::take_interest().unwrap_or_else(Interest::always);
225 }
226
227 Interest::always()
228 }
229
230 fn enabled(&self, _: &Metadata<'_>) -> bool {
231 if self.has_per_layer_filters() {
232 return FilterState::event_enabled();
233 }
234 true
235 }
236
237 #[inline]
238 fn new_span(&self, attrs: &span::Attributes<'_>) -> span::Id {
239 let parent = if attrs.is_root() {
240 None
241 } else if attrs.is_contextual() {
242 self.current_span().id().map(|id| self.clone_span(id))
243 } else {
244 attrs.parent().map(|id| self.clone_span(id))
245 };
246
247 let id = self
248 .spans
249 .create_with(|data| {
254 data.metadata = attrs.metadata();
255 data.parent = parent;
256 data.filter_map = crate::filter::FILTERING.with(|filtering| filtering.filter_map());
257 #[cfg(debug_assertions)]
258 {
259 if data.filter_map != FilterMap::new() {
260 debug_assert!(self.has_per_layer_filters());
261 }
262 }
263
264 let refs = data.ref_count.get_mut();
265 debug_assert_eq!(*refs, 0);
266 *refs = 1;
267 })
268 .expect("Unable to allocate another span");
269 idx_to_id(id)
270 }
271
272 #[inline]
275 fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
276
277 fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}
278
279 fn event_enabled(&self, _event: &Event<'_>) -> bool {
280 if self.has_per_layer_filters() {
281 return FilterState::event_enabled();
282 }
283 true
284 }
285
286 fn event(&self, _: &Event<'_>) {}
289
290 fn enter(&self, id: &span::Id) {
291 self.current_spans
292 .get_or_default()
293 .borrow_mut()
294 .push(id.clone());
295 }
296
297 fn exit(&self, id: &span::Id) {
298 if let Some(spans) = self.current_spans.get() {
299 spans.borrow_mut().pop(id);
300 }
301 }
302
303 fn clone_span(&self, id: &span::Id) -> span::Id {
304 let span = self
305 .get(id)
306 .unwrap_or_else(|| panic!(
307 "tried to clone {:?}, but no span exists with that ID\n\
308 This may be caused by consuming a parent span (`parent: span`) rather than borrowing it (`parent: &span`).",
309 id,
310 ));
311 let refs = span.ref_count.fetch_add(1, Ordering::Relaxed);
317 assert_ne!(
318 refs, 0,
319 "tried to clone a span ({:?}) that already closed",
320 id
321 );
322 id.clone()
323 }
324
325 fn current_span(&self) -> Current {
326 self.current_spans
327 .get()
328 .and_then(|spans| {
329 let spans = spans.borrow();
330 let id = spans.current()?;
331 let span = self.get(id)?;
332 Some(Current::new(id.clone(), span.metadata))
333 })
334 .unwrap_or_else(Current::none)
335 }
336
337 fn try_close(&self, id: span::Id) -> bool {
342 let span = match self.get(&id) {
343 Some(span) => span,
344 None if std::thread::panicking() => return false,
345 None => panic!("tried to drop a ref to {:?}, but no such span exists!", id),
346 };
347
348 let refs = span.ref_count.fetch_sub(1, Ordering::Release);
349 if !std::thread::panicking() {
350 assert!(refs < usize::MAX, "reference count overflow!");
351 }
352 if refs > 1 {
353 return false;
354 }
355
356 fence(Ordering::Acquire);
360 true
361 }
362}
363
364impl<'a> LookupSpan<'a> for Registry {
365 type Data = Data<'a>;
366
367 fn span_data(&'a self, id: &Id) -> Option<Self::Data> {
368 let inner = self.get(id)?;
369 Some(Data { inner })
370 }
371
372 fn register_filter(&mut self) -> FilterId {
373 let id = FilterId::new(self.next_filter_id);
374 self.next_filter_id += 1;
375 id
376 }
377}
378
379impl CloseGuard<'_> {
382 pub(crate) fn set_closing(&mut self) {
383 self.is_closing = true;
384 }
385}
386
387impl Drop for CloseGuard<'_> {
388 fn drop(&mut self) {
389 let _ = CLOSE_COUNT.try_with(|count| {
393 let c = count.get();
394 count.set(c - 1);
401
402 if c == 1 && self.is_closing {
406 self.registry.spans.clear(id_to_idx(&self.id));
407 }
408 });
409 }
410}
411
412impl<'a> SpanData<'a> for Data<'a> {
415 fn id(&self) -> Id {
416 idx_to_id(self.inner.key())
417 }
418
419 fn metadata(&self) -> &'static Metadata<'static> {
420 self.inner.metadata
421 }
422
423 fn parent(&self) -> Option<&Id> {
424 self.inner.parent.as_ref()
425 }
426
427 fn extensions(&self) -> Extensions<'_> {
428 Extensions::new(self.inner.extensions.read().expect("Mutex poisoned"))
429 }
430
431 fn extensions_mut(&self) -> ExtensionsMut<'_> {
432 ExtensionsMut::new(self.inner.extensions.write().expect("Mutex poisoned"))
433 }
434
435 #[inline]
436 fn is_enabled_for(&self, filter: FilterId) -> bool {
437 self.inner.filter_map.is_enabled(filter)
438 }
439}
440
441impl Default for DataInner {
444 fn default() -> Self {
445 struct NullCallsite;
450 impl tracing_core::callsite::Callsite for NullCallsite {
451 fn set_interest(&self, _: Interest) {
452 unreachable!(
453 "/!\\ Tried to register the null callsite /!\\\n \
454 This should never have happened and is definitely a bug. \
455 A `tracing` bug report would be appreciated."
456 )
457 }
458
459 fn metadata(&self) -> &Metadata<'_> {
460 unreachable!(
461 "/!\\ Tried to access the null callsite's metadata /!\\\n \
462 This should never have happened and is definitely a bug. \
463 A `tracing` bug report would be appreciated."
464 )
465 }
466 }
467
468 static NULL_CALLSITE: NullCallsite = NullCallsite;
469 static NULL_METADATA: Metadata<'static> = tracing_core::metadata! {
470 name: "",
471 target: "",
472 level: tracing_core::Level::TRACE,
473 fields: &[],
474 callsite: &NULL_CALLSITE,
475 kind: tracing_core::metadata::Kind::SPAN,
476 };
477
478 Self {
479 filter_map: FilterMap::new(),
480 metadata: &NULL_METADATA,
481 parent: None,
482 ref_count: AtomicUsize::new(0),
483 extensions: RwLock::new(ExtensionsInner::new()),
484 }
485 }
486}
487
488impl Clear for DataInner {
489 fn clear(&mut self) {
491 if self.parent.is_some() {
502 let subscriber = dispatcher::get_default(Dispatch::clone);
509 if let Some(parent) = self.parent.take() {
510 let _ = subscriber.try_close(parent);
511 }
512 }
513
514 self.extensions
516 .get_mut()
517 .unwrap_or_else(|l| {
518 l.into_inner()
521 })
522 .clear();
523
524 self.filter_map = FilterMap::new();
525 }
526}
527
528#[cfg(test)]
529mod tests {
530 use super::*;
531 use crate::{layer::Context, registry::LookupSpan, Layer};
532 use std::{
533 collections::HashMap,
534 dbg, println,
535 sync::{Arc, Mutex, Weak},
536 vec::Vec,
537 };
538 use tracing::{self, subscriber::with_default};
539 use tracing_core::{
540 dispatcher,
541 span::{Attributes, Id},
542 Subscriber,
543 };
544
545 struct AssertionLayer;
546 impl<S> Layer<S> for AssertionLayer
547 where
548 S: Subscriber + for<'a> LookupSpan<'a>,
549 {
550 fn on_close(&self, id: Id, ctx: Context<'_, S>) {
551 dbg!(format_args!("closing {:?}", id));
552 assert!(&ctx.span(&id).is_some());
553 }
554 }
555
556 #[test]
557 fn single_layer_can_access_closed_span() {
558 let subscriber = AssertionLayer.with_subscriber(Registry::default());
559
560 with_default(subscriber, || {
561 let span = tracing::debug_span!("span");
562 drop(span);
563 });
564 }
565
566 #[test]
567 fn multiple_layers_can_access_closed_span() {
568 let subscriber = AssertionLayer
569 .and_then(AssertionLayer)
570 .with_subscriber(Registry::default());
571
572 with_default(subscriber, || {
573 let span = tracing::debug_span!("span");
574 drop(span);
575 });
576 }
577
578 struct CloseLayer {
579 inner: Arc<Mutex<CloseState>>,
580 }
581
582 struct CloseHandle {
583 state: Arc<Mutex<CloseState>>,
584 }
585
586 #[derive(Default)]
587 struct CloseState {
588 open: HashMap<&'static str, Weak<()>>,
589 closed: Vec<(&'static str, Weak<()>)>,
590 }
591
592 #[allow(dead_code)] struct SetRemoved(Arc<()>);
594
595 impl<S> Layer<S> for CloseLayer
596 where
597 S: Subscriber + for<'a> LookupSpan<'a>,
598 {
599 fn on_new_span(&self, _: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
600 let span = ctx.span(id).expect("Missing span; this is a bug");
601 let mut lock = self.inner.lock().unwrap();
602 let is_removed = Arc::new(());
603 assert!(
604 lock.open
605 .insert(span.name(), Arc::downgrade(&is_removed))
606 .is_none(),
607 "test layer saw multiple spans with the same name, the test is probably messed up"
608 );
609 let mut extensions = span.extensions_mut();
610 extensions.insert(SetRemoved(is_removed));
611 }
612
613 fn on_close(&self, id: Id, ctx: Context<'_, S>) {
614 let span = if let Some(span) = ctx.span(&id) {
615 span
616 } else {
617 println!(
618 "span {:?} did not exist in `on_close`, are we panicking?",
619 id
620 );
621 return;
622 };
623 let name = span.name();
624 println!("close {} ({:?})", name, id);
625 if let Ok(mut lock) = self.inner.lock() {
626 if let Some(is_removed) = lock.open.remove(name) {
627 assert!(is_removed.upgrade().is_some());
628 lock.closed.push((name, is_removed));
629 }
630 }
631 }
632 }
633
634 impl CloseLayer {
635 fn new() -> (Self, CloseHandle) {
636 let state = Arc::new(Mutex::new(CloseState::default()));
637 (
638 Self {
639 inner: state.clone(),
640 },
641 CloseHandle { state },
642 )
643 }
644 }
645
646 impl CloseState {
647 fn is_open(&self, span: &str) -> bool {
648 self.open.contains_key(span)
649 }
650
651 fn is_closed(&self, span: &str) -> bool {
652 self.closed.iter().any(|(name, _)| name == &span)
653 }
654 }
655
656 impl CloseHandle {
657 fn assert_closed(&self, span: &str) {
658 let lock = self.state.lock().unwrap();
659 assert!(
660 lock.is_closed(span),
661 "expected {} to be closed{}",
662 span,
663 if lock.is_open(span) {
664 " (it was still open)"
665 } else {
666 ", but it never existed (is there a problem with the test?)"
667 }
668 )
669 }
670
671 fn assert_open(&self, span: &str) {
672 let lock = self.state.lock().unwrap();
673 assert!(
674 lock.is_open(span),
675 "expected {} to be open{}",
676 span,
677 if lock.is_closed(span) {
678 " (it was still open)"
679 } else {
680 ", but it never existed (is there a problem with the test?)"
681 }
682 )
683 }
684
685 fn assert_removed(&self, span: &str) {
686 let lock = self.state.lock().unwrap();
687 let is_removed = match lock.closed.iter().find(|(name, _)| name == &span) {
688 Some((_, is_removed)) => is_removed,
689 None => panic!(
690 "expected {} to be removed from the registry, but it was not closed {}",
691 span,
692 if lock.is_closed(span) {
693 " (it was still open)"
694 } else {
695 ", but it never existed (is there a problem with the test?)"
696 }
697 ),
698 };
699 assert!(
700 is_removed.upgrade().is_none(),
701 "expected {} to have been removed from the registry",
702 span
703 )
704 }
705
706 fn assert_not_removed(&self, span: &str) {
707 let lock = self.state.lock().unwrap();
708 let is_removed = match lock.closed.iter().find(|(name, _)| name == &span) {
709 Some((_, is_removed)) => is_removed,
710 None if lock.is_open(span) => return,
711 None => unreachable!(),
712 };
713 assert!(
714 is_removed.upgrade().is_some(),
715 "expected {} to have been removed from the registry",
716 span
717 )
718 }
719
720 #[allow(unused)] fn assert_last_closed(&self, span: Option<&str>) {
722 let lock = self.state.lock().unwrap();
723 let last = lock.closed.last().map(|(span, _)| span);
724 assert_eq!(
725 last,
726 span.as_ref(),
727 "expected {:?} to have closed last",
728 span
729 );
730 }
731
732 fn assert_closed_in_order(&self, order: impl AsRef<[&'static str]>) {
733 let lock = self.state.lock().unwrap();
734 let order = order.as_ref();
735 for (i, name) in order.iter().enumerate() {
736 assert_eq!(
737 lock.closed.get(i).map(|(span, _)| span),
738 Some(name),
739 "expected close order: {:?}, actual: {:?}",
740 order,
741 lock.closed.iter().map(|(name, _)| name).collect::<Vec<_>>()
742 );
743 }
744 }
745 }
746
747 #[test]
748 fn spans_are_removed_from_registry() {
749 let (close_layer, state) = CloseLayer::new();
750 let subscriber = AssertionLayer
751 .and_then(close_layer)
752 .with_subscriber(Registry::default());
753
754 let dispatch = dispatcher::Dispatch::new(subscriber);
760
761 dispatcher::with_default(&dispatch, || {
762 let span = tracing::debug_span!("span1");
763 drop(span);
764 let span = tracing::info_span!("span2");
765 drop(span);
766 });
767
768 state.assert_removed("span1");
769 state.assert_removed("span2");
770
771 drop(dispatch);
773 }
774
775 #[test]
776 fn spans_are_only_closed_when_the_last_ref_drops() {
777 let (close_layer, state) = CloseLayer::new();
778 let subscriber = AssertionLayer
779 .and_then(close_layer)
780 .with_subscriber(Registry::default());
781
782 let dispatch = dispatcher::Dispatch::new(subscriber);
788
789 let span2 = dispatcher::with_default(&dispatch, || {
790 let span = tracing::debug_span!("span1");
791 drop(span);
792 let span2 = tracing::info_span!("span2");
793 let span2_clone = span2.clone();
794 drop(span2);
795 span2_clone
796 });
797
798 state.assert_removed("span1");
799 state.assert_not_removed("span2");
800
801 drop(span2);
802 state.assert_removed("span1");
803
804 drop(dispatch);
806 }
807
808 #[test]
809 fn span_enter_guards_are_dropped_out_of_order() {
810 let (close_layer, state) = CloseLayer::new();
811 let subscriber = AssertionLayer
812 .and_then(close_layer)
813 .with_subscriber(Registry::default());
814
815 let dispatch = dispatcher::Dispatch::new(subscriber);
821
822 dispatcher::with_default(&dispatch, || {
823 let span1 = tracing::debug_span!("span1");
824 let span2 = tracing::info_span!("span2");
825
826 let enter1 = span1.enter();
827 let enter2 = span2.enter();
828
829 drop(enter1);
830 drop(span1);
831
832 state.assert_removed("span1");
833 state.assert_not_removed("span2");
834
835 drop(enter2);
836 state.assert_not_removed("span2");
837
838 drop(span2);
839 state.assert_removed("span1");
840 state.assert_removed("span2");
841 });
842 }
843
844 #[test]
845 fn child_closes_parent() {
846 let (close_layer, state) = CloseLayer::new();
851 let subscriber = close_layer.with_subscriber(Registry::default());
852
853 let dispatch = dispatcher::Dispatch::new(subscriber);
854
855 dispatcher::with_default(&dispatch, || {
856 let span1 = tracing::info_span!("parent");
857 let span2 = tracing::info_span!(parent: &span1, "child");
858
859 state.assert_open("parent");
860 state.assert_open("child");
861
862 drop(span1);
863 state.assert_open("parent");
864 state.assert_open("child");
865
866 drop(span2);
867 state.assert_closed("parent");
868 state.assert_closed("child");
869 });
870 }
871
872 #[test]
873 fn child_closes_grandparent() {
874 let (close_layer, state) = CloseLayer::new();
878 let subscriber = close_layer.with_subscriber(Registry::default());
879
880 let dispatch = dispatcher::Dispatch::new(subscriber);
881
882 dispatcher::with_default(&dispatch, || {
883 let span1 = tracing::info_span!("grandparent");
884 let span2 = tracing::info_span!(parent: &span1, "parent");
885 let span3 = tracing::info_span!(parent: &span2, "child");
886
887 state.assert_open("grandparent");
888 state.assert_open("parent");
889 state.assert_open("child");
890
891 drop(span1);
892 drop(span2);
893 state.assert_open("grandparent");
894 state.assert_open("parent");
895 state.assert_open("child");
896
897 drop(span3);
898
899 state.assert_closed_in_order(["child", "parent", "grandparent"]);
900 });
901 }
902}