mirror of
https://github.com/tokio-rs/tracing.git
synced 2025-10-02 23:34:40 +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::{
|
||||
any::{Any, TypeId},
|
||||
boxed::Box,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
/// 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)
|
||||
}
|
||||
}
|
||||
|
||||
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]
|
||||
extern crate tracing;
|
||||
use tracing::{
|
||||
span,
|
||||
field::display,
|
||||
span::{Attributes, Id, Record},
|
||||
subscriber::{with_default, Interest, Subscriber},
|
||||
Event, Level, Metadata,
|
||||
};
|
||||
|
||||
mod support;
|
||||
|
||||
use self::support::*;
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
|
||||
#[test]
|
||||
fn event_macros_dont_infinite_loop() {
|
||||
@ -33,25 +38,98 @@ fn event_macros_dont_infinite_loop() {
|
||||
true
|
||||
}
|
||||
|
||||
fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
|
||||
span::Id::from_u64(0xAAAA)
|
||||
fn new_span(&self, _: &Attributes<'_>) -> Id {
|
||||
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<'_>) {
|
||||
assert!(event.metadata().fields().iter().any(|f| f.name() == "foo"));
|
||||
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, || {
|
||||
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