use tracing_core::{field::FieldSet, span::Id, Metadata};
mod extensions;
#[cfg(feature = "registry")]
mod sharded;
#[cfg(feature = "registry")]
mod stack;
pub use extensions::{Extensions, ExtensionsMut};
#[cfg(feature = "registry")]
#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
pub use sharded::Data;
#[cfg(feature = "registry")]
#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
pub use sharded::Registry;
pub trait LookupSpan<'a> {
type Data: SpanData<'a>;
fn span_data(&'a self, id: &Id) -> Option<Self::Data>;
fn span(&'a self, id: &Id) -> Option<SpanRef<'_, Self>>
where
Self: Sized,
{
let data = self.span_data(&id)?;
Some(SpanRef {
registry: self,
data,
})
}
}
pub trait SpanData<'a> {
fn id(&self) -> Id;
fn metadata(&self) -> &'static Metadata<'static>;
fn parent(&self) -> Option<&Id>;
fn extensions(&self) -> Extensions<'_>;
fn extensions_mut(&self) -> ExtensionsMut<'_>;
}
#[derive(Debug)]
pub struct SpanRef<'a, R: LookupSpan<'a>> {
registry: &'a R,
data: R::Data,
}
#[derive(Debug)]
pub struct Parents<'a, R> {
registry: &'a R,
next: Option<Id>,
}
pub struct FromRoot<'a, R: LookupSpan<'a>> {
#[cfg(feature = "smallvec")]
inner: std::iter::Rev<smallvec::IntoIter<SpanRefVecArray<'a, R>>>,
#[cfg(not(feature = "smallvec"))]
inner: std::iter::Rev<std::vec::IntoIter<SpanRef<'a, R>>>,
}
#[cfg(feature = "smallvec")]
type SpanRefVecArray<'span, L> = [SpanRef<'span, L>; 16];
impl<'a, R> SpanRef<'a, R>
where
R: LookupSpan<'a>,
{
pub fn id(&self) -> Id {
self.data.id()
}
pub fn metadata(&self) -> &'static Metadata<'static> {
self.data.metadata()
}
pub fn name(&self) -> &'static str {
self.data.metadata().name()
}
pub fn fields(&self) -> &FieldSet {
self.data.metadata().fields()
}
pub fn parent_id(&self) -> Option<&Id> {
self.data.parent()
}
pub fn parent(&self) -> Option<Self> {
let id = self.data.parent()?;
let data = self.registry.span_data(id)?;
Some(Self {
registry: self.registry,
data,
})
}
pub fn parents(&self) -> Parents<'a, R> {
Parents {
registry: self.registry,
next: self.parent().map(|parent| parent.id()),
}
}
pub fn from_root(&self) -> FromRoot<'a, R> {
#[cfg(feature = "smallvec")]
type SpanRefVec<'span, L> = smallvec::SmallVec<SpanRefVecArray<'span, L>>;
#[cfg(not(feature = "smallvec"))]
type SpanRefVec<'span, L> = Vec<SpanRef<'span, L>>;
let parents = self.parents().collect::<SpanRefVec<'a, _>>();
let inner = parents.into_iter().rev();
FromRoot { inner }
}
pub fn extensions(&self) -> Extensions<'_> {
self.data.extensions()
}
pub fn extensions_mut(&self) -> ExtensionsMut<'_> {
self.data.extensions_mut()
}
}
impl<'a, R> Iterator for Parents<'a, R>
where
R: LookupSpan<'a>,
{
type Item = SpanRef<'a, R>;
fn next(&mut self) -> Option<Self::Item> {
let id = self.next.take()?;
let span = self.registry.span(&id)?;
self.next = span.parent().map(|parent| parent.id());
Some(span)
}
}
impl<'span, R> Iterator for FromRoot<'span, R>
where
R: LookupSpan<'span>,
{
type Item = SpanRef<'span, R>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'span, R> std::fmt::Debug for FromRoot<'span, R>
where
R: LookupSpan<'span>,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.pad("FromRoot { .. }")
}
}