Skip to content

Commit

Permalink
subscriber: unify span traversal (tokio-rs#1431)
Browse files Browse the repository at this point in the history
## Motivation

Fixes tokio-rs#1429 

## Solution

Implemented as described in tokio-rs#1429, and migrated all internal uses of the
deprecated methods. All tests passed both before and after the migration
(9ec8130).

- Add a new method `SpanRef::scope(&self)` that returns a leaf-to-root
  `Iterator`, including the specified leaf
- Add a new method `Scope::from_root(self)` (where `Scope` is the type
  returned by `SpanRef::scope` defined earlier) that returns a
  root-to-leaf `Iterator` that ends at the current leaf (in other
  words: it's essentially the same as
  `Scope::collect::<Vec<_>>().into_iter().rev()`)
- Deprecate all existing iterators, since they can be replaced by the
  new unified mechanism:
  - `Span::parents` is equivalent to `Span::scope().skip(1)` (although
    the `skip` is typically a bug)
  - `Span::from_root` is equivalent to `Span::scope().skip(1).from_root()`
    (although the `skip` is typically a bug)
  - `Context::scope` is equivalent to
    `Context::lookup_current().scope().from_root()` (although the
    `lookup_current` is sometimes a bug, see also tokio-rs#1428)
  • Loading branch information
nightkr authored and kaffarell committed May 22, 2024
1 parent c155dbf commit c322ec1
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 33 deletions.
15 changes: 11 additions & 4 deletions tracing-subscriber/src/fmt/fmt_layer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
field::RecordFields,
fmt::{format, FormatEvent, FormatFields, MakeWriter, TestWriter},
layer::{self, Context, Scope},
layer::{self, Context},
registry::{LookupSpan, SpanRef},
};
use format::{FmtSpan, TimingDisplay};
Expand Down Expand Up @@ -804,8 +804,10 @@ where
F: FnMut(&SpanRef<'_, S>) -> Result<(), E>,
{
// visit all the current spans
for span in self.ctx.scope() {
f(&span)?;
if let Some(leaf) = self.ctx.lookup_current() {
for span in leaf.scope().from_root() {
f(&span)?;
}
}
Ok(())
}
Expand Down Expand Up @@ -864,7 +866,12 @@ where
/// the current span.
///
/// [stored data]: ../registry/struct.SpanRef.html
pub fn scope(&self) -> Scope<'_, S>
#[deprecated(
note = "wraps layer::Context::scope, which is deprecated",
since = "0.2.19"
)]
#[allow(deprecated)]
pub fn scope(&self) -> crate::layer::Scope<'_, S>
where
S: for<'lookup> LookupSpan<'lookup>,
{
Expand Down
96 changes: 67 additions & 29 deletions tracing-subscriber/src/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,9 +580,24 @@ pub struct Identity {
/// [`Context::scope`]: struct.Context.html#method.scope
#[cfg(feature = "registry")]
#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
pub struct Scope<'a, L: LookupSpan<'a>>(
Option<std::iter::Chain<registry::FromRoot<'a, L>, std::iter::Once<SpanRef<'a, L>>>>,
);
#[deprecated(note = "renamed to crate::registry::ScopeFromRoot", since = "0.2.19")]
#[derive(Debug)]
pub struct Scope<'a, L>(std::iter::Flatten<std::option::IntoIter<registry::ScopeFromRoot<'a, L>>>)
where
L: LookupSpan<'a>;

#[cfg(feature = "registry")]
#[allow(deprecated)]
impl<'a, L> Iterator for Scope<'a, L>
where
L: LookupSpan<'a>,
{
type Item = SpanRef<'a, L>;

fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}

// === impl Layered ===

Expand Down Expand Up @@ -1096,15 +1111,59 @@ where
/// [stored data]: ../registry/struct.SpanRef.html
#[cfg(feature = "registry")]
#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
#[deprecated(
note = "equivalent to `self.current_span().id().and_then(|id| self.span_scope(id).from_root())` but consider passing an explicit ID instead of relying on the contextual span",
since = "0.2.19"
)]
#[allow(deprecated)]
pub fn scope(&self) -> Scope<'_, S>
where
S: for<'lookup> registry::LookupSpan<'lookup>,
{
let scope = self.lookup_current().map(|span| {
let parents = span.from_root();
parents.chain(std::iter::once(span))
});
Scope(scope)
Scope(
self.lookup_current()
.as_ref()
.map(registry::SpanRef::scope)
.map(registry::Scope::from_root)
.into_iter()
.flatten(),
)
}

/// Returns an iterator over the [stored data] for all the spans in the
/// current context, starting with the specified span and ending with the
/// root of the trace tree and ending with the current span.
///
/// <div class="information">
/// <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div>
/// </div>
/// <div class="example-wrap" style="display:inline-block">
/// <pre class="ignore" style="white-space:normal;font:inherit;">
/// <strong>Note</strong>: Compared to <a href="#method.scope"><code>scope</code></a> this
/// returns the spans in reverse order (from leaf to root). Use
/// <a href="../registry/struct.Scope.html#method.from_root"><code>Scope::from_root</code></a>
/// in case root-to-leaf ordering is desired.
/// </pre></div>
///
/// <div class="information">
/// <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div>
/// </div>
/// <div class="example-wrap" style="display:inline-block">
/// <pre class="ignore" style="white-space:normal;font:inherit;">
/// <strong>Note</strong>: This requires the wrapped subscriber to implement the
/// <a href="../registry/trait.LookupSpan.html"><code>LookupSpan</code></a> trait.
/// See the documentation on <a href="./struct.Context.html"><code>Context</code>'s
/// declaration</a> for details.
/// </pre></div>
///
/// [stored data]: ../registry/struct.SpanRef.html
#[cfg(feature = "registry")]
#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
pub fn span_scope(&self, id: &span::Id) -> Option<registry::Scope<'_, S>>
where
S: for<'lookup> registry::LookupSpan<'lookup>,
{
Some(self.span(id)?.scope())
}
}

Expand Down Expand Up @@ -1133,27 +1192,6 @@ impl Identity {
}
}

// === impl Scope ===

#[cfg(feature = "registry")]
#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
impl<'a, L: LookupSpan<'a>> Iterator for Scope<'a, L> {
type Item = SpanRef<'a, L>;

#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.as_mut()?.next()
}
}

#[cfg(feature = "registry")]
#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
impl<'a, L: LookupSpan<'a>> std::fmt::Debug for Scope<'a, L> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.pad("Scope { .. }")
}
}

#[cfg(test)]
pub(crate) mod tests {
use super::*;
Expand Down

0 comments on commit c322ec1

Please sign in to comment.