mirror of
				https://github.com/tokio-rs/tracing.git
				synced 2025-11-03 23:12:56 +00:00 
			
		
		
		
	core: add support for Arc<dyn Subscriber + ...>
				
					
				
			## Motivation (#1374) Users may wish to erase the type of a `Subscriber` implementation, such as when it is dynamically constructed from a complex parameterized type. PR #1358 added a `Subscriber` implementation for `Box<dyn Subscriber + Send + Sync + 'static>`, allowing the use of type-erased trait objects. In some cases, it may also be useful to share a type-erased subscriber, _without_ using `Dispatch` --- such as when different sets of `tracing-subscriber` subscribers are layered on one shared subscriber. ## Solution This branch builds on #1358 by adding an `impl Subscriber for Arc<dyn Subscriber + Send + Sync + 'static>`. I also added quick tests for both `Arc`ed and `Box`ed subscribers. Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This commit is contained in:
		
							parent
							
								
									f9a3f17fbb
								
							
						
					
					
						commit
						ccfa2cc687
					
				@ -4,6 +4,7 @@ use crate::{span, Event, LevelFilter, Metadata};
 | 
				
			|||||||
use crate::stdlib::{
 | 
					use crate::stdlib::{
 | 
				
			||||||
    any::{Any, TypeId},
 | 
					    any::{Any, TypeId},
 | 
				
			||||||
    boxed::Box,
 | 
					    boxed::Box,
 | 
				
			||||||
 | 
					    sync::Arc,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Trait representing the functions required to collect trace data.
 | 
					/// Trait representing the functions required to collect trace data.
 | 
				
			||||||
@ -639,3 +640,80 @@ impl Subscriber for Box<dyn Subscriber + Send + Sync + 'static> {
 | 
				
			|||||||
        self.as_ref().downcast_raw(id)
 | 
					        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)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -9,11 +9,16 @@
 | 
				
			|||||||
#[macro_use]
 | 
					#[macro_use]
 | 
				
			||||||
extern crate tracing;
 | 
					extern crate tracing;
 | 
				
			||||||
use tracing::{
 | 
					use tracing::{
 | 
				
			||||||
    span,
 | 
					    field::display,
 | 
				
			||||||
 | 
					    span::{Attributes, Id, Record},
 | 
				
			||||||
    subscriber::{with_default, Interest, Subscriber},
 | 
					    subscriber::{with_default, Interest, Subscriber},
 | 
				
			||||||
    Event, Level, Metadata,
 | 
					    Event, Level, Metadata,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod support;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use self::support::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
 | 
					#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
 | 
				
			||||||
#[test]
 | 
					#[test]
 | 
				
			||||||
fn event_macros_dont_infinite_loop() {
 | 
					fn event_macros_dont_infinite_loop() {
 | 
				
			||||||
@ -33,25 +38,98 @@ fn event_macros_dont_infinite_loop() {
 | 
				
			|||||||
            true
 | 
					            true
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
 | 
					        fn new_span(&self, _: &Attributes<'_>) -> Id {
 | 
				
			||||||
            span::Id::from_u64(0xAAAA)
 | 
					            Id::from_u64(0xAAAA)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
 | 
					        fn record(&self, _: &Id, _: &Record<'_>) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
 | 
					        fn record_follows_from(&self, _: &Id, _: &Id) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fn event(&self, event: &Event<'_>) {
 | 
					        fn event(&self, event: &Event<'_>) {
 | 
				
			||||||
            assert!(event.metadata().fields().iter().any(|f| f.name() == "foo"));
 | 
					            assert!(event.metadata().fields().iter().any(|f| f.name() == "foo"));
 | 
				
			||||||
            event!(Level::TRACE, baz = false);
 | 
					            event!(Level::TRACE, baz = false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fn enter(&self, _: &span::Id) {}
 | 
					        fn enter(&self, _: &Id) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fn exit(&self, _: &span::Id) {}
 | 
					        fn exit(&self, _: &Id) {}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with_default(TestSubscriber, || {
 | 
					    with_default(TestSubscriber, || {
 | 
				
			||||||
        event!(Level::TRACE, foo = false);
 | 
					        event!(Level::TRACE, foo = false);
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
 | 
				
			||||||
 | 
					#[test]
 | 
				
			||||||
 | 
					fn boxed_subscriber() {
 | 
				
			||||||
 | 
					    let (subscriber, handle) = subscriber::mock()
 | 
				
			||||||
 | 
					        .new_span(
 | 
				
			||||||
 | 
					            span::mock().named("foo").with_field(
 | 
				
			||||||
 | 
					                field::mock("bar")
 | 
				
			||||||
 | 
					                    .with_value(&display("hello from my span"))
 | 
				
			||||||
 | 
					                    .only(),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .enter(span::mock().named("foo"))
 | 
				
			||||||
 | 
					        .exit(span::mock().named("foo"))
 | 
				
			||||||
 | 
					        .drop_span(span::mock().named("foo"))
 | 
				
			||||||
 | 
					        .done()
 | 
				
			||||||
 | 
					        .run_with_handle();
 | 
				
			||||||
 | 
					    let subscriber: Box<dyn Subscriber + Send + Sync + 'static> = Box::new(subscriber);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with_default(subscriber, || {
 | 
				
			||||||
 | 
					        let from = "my span";
 | 
				
			||||||
 | 
					        let span = span!(
 | 
				
			||||||
 | 
					            Level::TRACE,
 | 
				
			||||||
 | 
					            "foo",
 | 
				
			||||||
 | 
					            bar = format_args!("hello from {}", from)
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        span.in_scope(|| {});
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    handle.assert_finished();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
 | 
				
			||||||
 | 
					#[test]
 | 
				
			||||||
 | 
					fn arced_subscriber() {
 | 
				
			||||||
 | 
					    use std::sync::Arc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let (subscriber, handle) = subscriber::mock()
 | 
				
			||||||
 | 
					        .new_span(
 | 
				
			||||||
 | 
					            span::mock().named("foo").with_field(
 | 
				
			||||||
 | 
					                field::mock("bar")
 | 
				
			||||||
 | 
					                    .with_value(&display("hello from my span"))
 | 
				
			||||||
 | 
					                    .only(),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .enter(span::mock().named("foo"))
 | 
				
			||||||
 | 
					        .exit(span::mock().named("foo"))
 | 
				
			||||||
 | 
					        .drop_span(span::mock().named("foo"))
 | 
				
			||||||
 | 
					        .event(
 | 
				
			||||||
 | 
					            event::mock()
 | 
				
			||||||
 | 
					                .with_fields(field::mock("message").with_value(&display("hello from my event"))),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .done()
 | 
				
			||||||
 | 
					        .run_with_handle();
 | 
				
			||||||
 | 
					    let subscriber: Arc<dyn Subscriber + Send + Sync + 'static> = Arc::new(subscriber);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Test using a clone of the `Arc`ed subscriber
 | 
				
			||||||
 | 
					    with_default(subscriber.clone(), || {
 | 
				
			||||||
 | 
					        let from = "my span";
 | 
				
			||||||
 | 
					        let span = span!(
 | 
				
			||||||
 | 
					            Level::TRACE,
 | 
				
			||||||
 | 
					            "foo",
 | 
				
			||||||
 | 
					            bar = format_args!("hello from {}", from)
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        span.in_scope(|| {});
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with_default(subscriber, || {
 | 
				
			||||||
 | 
					        tracing::info!("hello from my event");
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    handle.assert_finished();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user