mirror of
https://github.com/tokio-rs/tracing.git
synced 2025-11-03 15:03:00 +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