use {
callsite, span,
subscriber::{self, Subscriber},
Event, Metadata,
};
use std::{
cell::RefCell,
fmt,
sync::{Arc, Weak},
};
#[derive(Clone)]
pub struct Dispatch {
subscriber: Arc<Subscriber + Send + Sync>,
}
thread_local! {
static CURRENT_DISPATCH: RefCell<Dispatch> = RefCell::new(Dispatch::none());
}
pub fn with_default<T>(dispatcher: &Dispatch, f: impl FnOnce() -> T) -> T {
struct ResetGuard(Option<Dispatch>);
impl Drop for ResetGuard {
fn drop(&mut self) {
if let Some(dispatch) = self.0.take() {
let _ = CURRENT_DISPATCH.try_with(|current| {
*current.borrow_mut() = dispatch;
});
}
}
}
let dispatcher = dispatcher.clone();
let prior = CURRENT_DISPATCH.try_with(|current| current.replace(dispatcher));
let _guard = ResetGuard(prior.ok());
f()
}
pub fn get_default<T, F>(mut f: F) -> T
where
F: FnMut(&Dispatch) -> T,
{
CURRENT_DISPATCH
.try_with(|current| f(&*current.borrow()))
.unwrap_or_else(|_| f(&Dispatch::none()))
}
pub(crate) struct Registrar(Weak<Subscriber + Send + Sync>);
impl Dispatch {
pub fn none() -> Self {
Dispatch {
subscriber: Arc::new(NoSubscriber),
}
}
pub fn new<S>(subscriber: S) -> Self
where
S: Subscriber + Send + Sync + 'static,
{
let me = Dispatch {
subscriber: Arc::new(subscriber),
};
callsite::register_dispatch(&me);
me
}
pub(crate) fn registrar(&self) -> Registrar {
Registrar(Arc::downgrade(&self.subscriber))
}
#[inline]
pub fn register_callsite(&self, metadata: &Metadata) -> subscriber::Interest {
self.subscriber.register_callsite(metadata)
}
#[inline]
pub fn new_span(&self, span: &span::Attributes) -> span::Id {
self.subscriber.new_span(span)
}
#[inline]
pub fn record(&self, span: &span::Id, values: &span::Record) {
self.subscriber.record(span, values)
}
#[inline]
pub fn record_follows_from(&self, span: &span::Id, follows: &span::Id) {
self.subscriber.record_follows_from(span, follows)
}
#[inline]
pub fn enabled(&self, metadata: &Metadata) -> bool {
self.subscriber.enabled(metadata)
}
#[inline]
pub fn event(&self, event: &Event) {
self.subscriber.event(event)
}
#[inline]
pub fn enter(&self, span: &span::Id) {
self.subscriber.enter(span)
}
#[inline]
pub fn exit(&self, span: &span::Id) {
self.subscriber.exit(span)
}
#[inline]
pub fn clone_span(&self, id: &span::Id) -> span::Id {
self.subscriber.clone_span(&id)
}
#[inline]
pub fn drop_span(&self, id: span::Id) {
self.subscriber.drop_span(id)
}
}
impl fmt::Debug for Dispatch {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("Dispatch(...)")
}
}
impl<S> From<S> for Dispatch
where
S: Subscriber + Send + Sync + 'static,
{
#[inline]
fn from(subscriber: S) -> Self {
Dispatch::new(subscriber)
}
}
struct NoSubscriber;
impl Subscriber for NoSubscriber {
#[inline]
fn register_callsite(&self, _: &Metadata) -> subscriber::Interest {
subscriber::Interest::never()
}
fn new_span(&self, _: &span::Attributes) -> span::Id {
span::Id::from_u64(0xDEAD)
}
fn event(&self, _event: &Event) {}
fn record(&self, _span: &span::Id, _values: &span::Record) {}
fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}
#[inline]
fn enabled(&self, _metadata: &Metadata) -> bool {
false
}
fn enter(&self, _span: &span::Id) {}
fn exit(&self, _span: &span::Id) {}
}
impl Registrar {
pub(crate) fn try_register(&self, metadata: &Metadata) -> Option<subscriber::Interest> {
self.0.upgrade().map(|s| s.register_callsite(metadata))
}
}