mirror of
https://github.com/tokio-rs/tracing.git
synced 2025-09-30 14:30:42 +00:00
core: add Subscriber
impl for Box<dyn Subscriber + ...>
(#1358)
In some cases, users may wish to erase the type of a `Subscriber` implementation, such as when it is dynamically constructed from a complex parameterized type. When doing so, it's important to ensure that all trait methods with default implementations are properly forwarded to the inner erased type. For example, if the type does not implement `try_close`, but the inner erased subscriber does, then the the subscriber will not be notified when spans close — which could result in a memory leak. To avoid potential footguns resulting from users implementing type-erased subscribers incorrectly, this branch adds a new `impl Subscriber for Box<dyn Subscriber + Send + Sync + 'static>` in `tracing-core`. This is also somewhat more ergonomic than any solution in another crate, since the implementation is for `Box<dyn Subscriber + ...>` directly, rather than some `BoxedSubscriber` newtype.
This commit is contained in:
parent
1e8446eaa0
commit
e63d8e454b
@ -1,7 +1,10 @@
|
||||
//! Subscribers collect and record trace data.
|
||||
use crate::{span, Event, LevelFilter, Metadata};
|
||||
|
||||
use crate::stdlib::any::{Any, TypeId};
|
||||
use crate::stdlib::{
|
||||
any::{Any, TypeId},
|
||||
boxed::Box,
|
||||
};
|
||||
|
||||
/// Trait representing the functions required to collect trace data.
|
||||
///
|
||||
@ -559,3 +562,80 @@ impl Interest {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Subscriber for Box<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)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user