console_subscriber/stack.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
use tracing_core::span::Id;
// This has been copied from tracing-subscriber. Once the library adds
// the ability to iterate over entered spans, this code will
// no longer be needed here
//
// https://github.com/tokio-rs/tracing/blob/master/tracing-subscriber/src/registry/stack.rs
#[derive(Debug, Clone)]
pub(crate) struct ContextId {
id: Id,
duplicate: bool,
}
impl ContextId {
pub fn id(&self) -> &Id {
&self.id
}
}
/// `SpanStack` tracks what spans are currently executing on a thread-local basis.
///
/// A "separate current span" for each thread is a semantic choice, as each span
/// can be executing in a different thread.
#[derive(Debug, Default)]
pub(crate) struct SpanStack {
stack: Vec<ContextId>,
}
impl SpanStack {
#[inline]
pub(crate) fn push(&mut self, id: Id) -> bool {
let duplicate = self.stack.iter().any(|i| i.id == id);
self.stack.push(ContextId { id, duplicate });
!duplicate
}
/// Pop a currently entered span.
///
/// Returns `true` if the span was actually exited.
#[inline]
pub(crate) fn pop(&mut self, expected_id: &Id) -> bool {
if let Some((idx, _)) = self
.stack
.iter()
.enumerate()
.rev()
.find(|(_, ctx_id)| ctx_id.id == *expected_id)
{
let ContextId { id: _, duplicate } = self.stack.remove(idx);
return !duplicate;
}
false
}
pub(crate) fn iter(&self) -> impl Iterator<Item = &Id> {
self.stack
.iter()
.filter_map(|ContextId { id, duplicate }| if *duplicate { None } else { Some(id) })
}
pub(crate) fn stack(&self) -> &Vec<ContextId> {
&self.stack
}
}