tokio_trace_core/
span.rs

1//! Spans represent periods of time in the execution of a program.
2
3use {field, Metadata};
4
5/// Identifies a span within the context of a subscriber.
6///
7/// They are generated by [`Subscriber`]s for each span as it is created, by
8/// the [`new_span`] trait method. See the documentation for that method for
9/// more information on span ID generation.
10///
11/// [`Subscriber`]: ../subscriber/trait.Subscriber.html
12/// [`new_span`]: ../subscriber/trait.Subscriber.html#method.new_span
13#[derive(Clone, Debug, PartialEq, Eq, Hash)]
14// TODO(eliza): when Tokio's minimum Rust version is >= 1.28, change the
15// internal representation to a `NonZeroU64`.
16pub struct Id(u64);
17
18/// Attributes provided to a `Subscriber` describing a new span when it is
19/// created.
20#[derive(Debug)]
21pub struct Attributes<'a> {
22    metadata: &'a Metadata<'a>,
23    values: &'a field::ValueSet<'a>,
24    parent: Parent,
25}
26
27/// A set of fields recorded by a span.
28#[derive(Debug)]
29pub struct Record<'a> {
30    values: &'a field::ValueSet<'a>,
31}
32
33#[derive(Debug)]
34enum Parent {
35    /// The new span will be a root span.
36    Root,
37    /// The new span will be rooted in the current span.
38    Current,
39    /// The new span has an explicitly-specified parent.
40    Explicit(Id),
41}
42
43// ===== impl Span =====
44
45impl Id {
46    /// Constructs a new span ID from the given `u64`.
47    ///
48    /// **Note**: Span IDs must be greater than zero.
49    ///
50    /// # Panics
51    /// - If the provided `u64` is 0
52    pub fn from_u64(u: u64) -> Self {
53        assert!(u > 0);
54        Id(u)
55    }
56
57    /// Returns the span's ID as a  `u64`.
58    pub fn into_u64(&self) -> u64 {
59        self.0
60    }
61}
62
63// ===== impl Attributes =====
64
65impl<'a> Attributes<'a> {
66    /// Returns `Attributes` describing a new child span of the current span,
67    /// with the provided metadata and values.
68    pub fn new(metadata: &'a Metadata<'a>, values: &'a field::ValueSet<'a>) -> Self {
69        Attributes {
70            metadata,
71            values,
72            parent: Parent::Current,
73        }
74    }
75
76    /// Returns `Attributes` describing a new span at the root of its own trace
77    /// tree, with the provided metadata and values.
78    pub fn new_root(metadata: &'a Metadata<'a>, values: &'a field::ValueSet<'a>) -> Self {
79        Attributes {
80            metadata,
81            values,
82            parent: Parent::Root,
83        }
84    }
85
86    /// Returns `Attributes` describing a new child span of the specified
87    /// parent span, with the provided metadata and values.
88    pub fn child_of(
89        parent: Id,
90        metadata: &'a Metadata<'a>,
91        values: &'a field::ValueSet<'a>,
92    ) -> Self {
93        Attributes {
94            metadata,
95            values,
96            parent: Parent::Explicit(parent),
97        }
98    }
99
100    /// Returns a reference to the new span's metadata.
101    pub fn metadata(&self) -> &Metadata<'a> {
102        self.metadata
103    }
104
105    /// Returns a reference to a `ValueSet` containing any values the new span
106    /// was created with.
107    pub fn values(&self) -> &field::ValueSet<'a> {
108        self.values
109    }
110
111    /// Returns true if the new span shoold be a root.
112    pub fn is_root(&self) -> bool {
113        match self.parent {
114            Parent::Root => true,
115            _ => false,
116        }
117    }
118
119    /// Returns true if the new span's parent should be determined based on the
120    /// current context.
121    ///
122    /// If this is true and the current thread is currently inside a span, then
123    /// that span should be the new span's parent. Otherwise, if the current
124    /// thread is _not_ inside a span, then the new span will be the root of its
125    /// own trace tree.
126    pub fn is_contextual(&self) -> bool {
127        match self.parent {
128            Parent::Current => true,
129            _ => false,
130        }
131    }
132
133    /// Returns the new span's explicitly-specified parent, if there is one.
134    ///
135    /// Otherwise (if the new span is a root or is a child of the current span),
136    /// returns false.
137    pub fn parent(&self) -> Option<&Id> {
138        match self.parent {
139            Parent::Explicit(ref p) => Some(p),
140            _ => None,
141        }
142    }
143
144    /// Records all the fields in this set of `Attributes` with the provided
145    /// [Visitor].
146    ///
147    /// [visitor]: ../field/trait.Visit.html
148    pub fn record(&self, visitor: &mut field::Visit) {
149        self.values.record(visitor)
150    }
151
152    /// Returns `true` if this set of `Attributes` contains a value for the
153    /// given `Field`.
154    pub fn contains(&self, field: &field::Field) -> bool {
155        self.values.contains(field)
156    }
157
158    /// Returns true if this set of `Attributes` contains _no_ values.
159    pub fn is_empty(&self) -> bool {
160        self.values.is_empty()
161    }
162}
163
164// ===== impl Record =====
165
166impl<'a> Record<'a> {
167    /// Constructs a new `Record` from a `ValueSet`.
168    pub fn new(values: &'a field::ValueSet<'a>) -> Self {
169        Self { values }
170    }
171
172    /// Records all the fields in this `Record` with the provided [Visitor].
173    ///
174    /// [visitor]: ../field/trait.Visit.html
175    pub fn record(&self, visitor: &mut field::Visit) {
176        self.values.record(visitor)
177    }
178
179    /// Returns `true` if this `Record` contains a value for the given `Field`.
180    pub fn contains(&self, field: &field::Field) -> bool {
181        self.values.contains(field)
182    }
183
184    /// Returns true if this `Record` contains _no_ values.
185    pub fn is_empty(&self) -> bool {
186        self.values.is_empty()
187    }
188}