1 //! Spans represent periods of time in the execution of a program.
2 use crate::field::FieldSet;
3 use crate::parent::Parent;
4 use crate::stdlib::num::NonZeroU64;
5 use crate::{field, Metadata};
6 
7 /// Identifies a span within the context of a subscriber.
8 ///
9 /// They are generated by [`Subscriber`]s for each span as it is created, by
10 /// the [`new_span`] trait method. See the documentation for that method for
11 /// more information on span ID generation.
12 ///
13 /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
14 /// [`new_span`]: ../subscriber/trait.Subscriber.html#method.new_span
15 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
16 pub struct Id(NonZeroU64);
17 
18 /// Attributes provided to a `Subscriber` describing a new span when it is
19 /// created.
20 #[derive(Debug)]
21 pub struct Attributes<'a> {
22     metadata: &'static Metadata<'static>,
23     values: &'a field::ValueSet<'a>,
24     parent: Parent,
25 }
26 
27 /// A set of fields recorded by a span.
28 #[derive(Debug)]
29 pub struct Record<'a> {
30     values: &'a field::ValueSet<'a>,
31 }
32 
33 /// Indicates what [the `Subscriber` considers] the "current" span.
34 ///
35 /// As subscribers may not track a notion of a current span, this has three
36 /// possible states:
37 /// - "unknown", indicating that the subscriber does not track a current span,
38 /// - "none", indicating that the current context is known to not be in a span,
39 /// - "some", with the current span's [`Id`] and [`Metadata`].
40 ///
41 /// [the `Subscriber` considers]: ../subscriber/trait.Subscriber.html#method.current_span
42 /// [`Id`]: struct.Id.html
43 /// [`Metadata`]: ../metadata/struct.Metadata.html
44 #[derive(Debug)]
45 pub struct Current {
46     inner: CurrentInner,
47 }
48 
49 #[derive(Debug)]
50 enum CurrentInner {
51     Current {
52         id: Id,
53         metadata: &'static Metadata<'static>,
54     },
55     None,
56     Unknown,
57 }
58 
59 // ===== impl Span =====
60 
61 impl Id {
62     /// Constructs a new span ID from the given `u64`.
63     ///
64     /// <div class="information">
65     ///     <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div>
66     /// </div>
67     /// <div class="example-wrap" style="display:inline-block">
68     /// <pre class="ignore" style="white-space:normal;font:inherit;">
69     /// <strong>Note</strong>: Span IDs must be greater than zero.</pre></div>
70     ///
71     /// # Panics
72     /// - If the provided `u64` is 0
from_u64(u: u64) -> Self73     pub fn from_u64(u: u64) -> Self {
74         Id(NonZeroU64::new(u).expect("span IDs must be > 0"))
75     }
76 
77     /// Constructs a new span ID from the given `NonZeroU64`.
78     ///
79     /// Unlike [`Id::from_u64`](#method.from_u64), this will never panic.
80     #[inline]
from_non_zero_u64(id: NonZeroU64) -> Self81     pub const fn from_non_zero_u64(id: NonZeroU64) -> Self {
82         Id(id)
83     }
84 
85     // Allow `into` by-ref since we don't want to impl Copy for Id
86     #[allow(clippy::wrong_self_convention)]
87     /// Returns the span's ID as a `u64`.
into_u64(&self) -> u6488     pub fn into_u64(&self) -> u64 {
89         self.0.get()
90     }
91 
92     // Allow `into` by-ref since we don't want to impl Copy for Id
93     #[allow(clippy::wrong_self_convention)]
94     /// Returns the span's ID as a `NonZeroU64`.
95     #[inline]
into_non_zero_u64(&self) -> NonZeroU6496     pub const fn into_non_zero_u64(&self) -> NonZeroU64 {
97         self.0
98     }
99 }
100 
101 impl<'a> From<&'a Id> for Option<Id> {
from(id: &'a Id) -> Self102     fn from(id: &'a Id) -> Self {
103         Some(id.clone())
104     }
105 }
106 
107 // ===== impl Attributes =====
108 
109 impl<'a> Attributes<'a> {
110     /// Returns `Attributes` describing a new child span of the current span,
111     /// with the provided metadata and values.
new(metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>) -> Self112     pub fn new(metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>) -> Self {
113         Attributes {
114             metadata,
115             values,
116             parent: Parent::Current,
117         }
118     }
119 
120     /// Returns `Attributes` describing a new span at the root of its own trace
121     /// tree, with the provided metadata and values.
new_root(metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>) -> Self122     pub fn new_root(metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>) -> Self {
123         Attributes {
124             metadata,
125             values,
126             parent: Parent::Root,
127         }
128     }
129 
130     /// Returns `Attributes` describing a new child span of the specified
131     /// parent span, with the provided metadata and values.
child_of( parent: Id, metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>, ) -> Self132     pub fn child_of(
133         parent: Id,
134         metadata: &'static Metadata<'static>,
135         values: &'a field::ValueSet<'a>,
136     ) -> Self {
137         Attributes {
138             metadata,
139             values,
140             parent: Parent::Explicit(parent),
141         }
142     }
143 
144     /// Returns a reference to the new span's metadata.
metadata(&self) -> &'static Metadata<'static>145     pub fn metadata(&self) -> &'static Metadata<'static> {
146         self.metadata
147     }
148 
149     /// Returns a reference to a `ValueSet` containing any values the new span
150     /// was created with.
values(&self) -> &field::ValueSet<'a>151     pub fn values(&self) -> &field::ValueSet<'a> {
152         self.values
153     }
154 
155     /// Returns true if the new span should be a root.
is_root(&self) -> bool156     pub fn is_root(&self) -> bool {
157         matches!(self.parent, Parent::Root)
158     }
159 
160     /// Returns true if the new span's parent should be determined based on the
161     /// current context.
162     ///
163     /// If this is true and the current thread is currently inside a span, then
164     /// that span should be the new span's parent. Otherwise, if the current
165     /// thread is _not_ inside a span, then the new span will be the root of its
166     /// own trace tree.
is_contextual(&self) -> bool167     pub fn is_contextual(&self) -> bool {
168         matches!(self.parent, Parent::Current)
169     }
170 
171     /// Returns the new span's explicitly-specified parent, if there is one.
172     ///
173     /// Otherwise (if the new span is a root or is a child of the current span),
174     /// returns false.
parent(&self) -> Option<&Id>175     pub fn parent(&self) -> Option<&Id> {
176         match self.parent {
177             Parent::Explicit(ref p) => Some(p),
178             _ => None,
179         }
180     }
181 
182     /// Records all the fields in this set of `Attributes` with the provided
183     /// [Visitor].
184     ///
185     /// [visitor]: ../field/trait.Visit.html
record(&self, visitor: &mut dyn field::Visit)186     pub fn record(&self, visitor: &mut dyn field::Visit) {
187         self.values.record(visitor)
188     }
189 
190     /// Returns `true` if this set of `Attributes` contains a value for the
191     /// given `Field`.
contains(&self, field: &field::Field) -> bool192     pub fn contains(&self, field: &field::Field) -> bool {
193         self.values.contains(field)
194     }
195 
196     /// Returns true if this set of `Attributes` contains _no_ values.
is_empty(&self) -> bool197     pub fn is_empty(&self) -> bool {
198         self.values.is_empty()
199     }
200 
201     /// Returns the set of all [fields] defined by this span's [`Metadata`].
202     ///
203     /// Note that the [`FieldSet`] returned by this method includes *all* the
204     /// fields declared by this span, not just those with values that are recorded
205     /// as part of this set of `Attributes`. Other fields with values not present in
206     /// this `Attributes`' value set may [record] values later.
207     ///
208     /// [fields]: crate::field
209     /// [record]: Attributes::record()
210     /// [`Metadata`]: crate::metadata::Metadata
211     /// [`FieldSet`]: crate::field::FieldSet
fields(&self) -> &FieldSet212     pub fn fields(&self) -> &FieldSet {
213         self.values.field_set()
214     }
215 }
216 
217 // ===== impl Record =====
218 
219 impl<'a> Record<'a> {
220     /// Constructs a new `Record` from a `ValueSet`.
new(values: &'a field::ValueSet<'a>) -> Self221     pub fn new(values: &'a field::ValueSet<'a>) -> Self {
222         Self { values }
223     }
224 
225     /// Records all the fields in this `Record` with the provided [Visitor].
226     ///
227     /// [visitor]: ../field/trait.Visit.html
record(&self, visitor: &mut dyn field::Visit)228     pub fn record(&self, visitor: &mut dyn field::Visit) {
229         self.values.record(visitor)
230     }
231 
232     /// Returns `true` if this `Record` contains a value for the given `Field`.
contains(&self, field: &field::Field) -> bool233     pub fn contains(&self, field: &field::Field) -> bool {
234         self.values.contains(field)
235     }
236 
237     /// Returns true if this `Record` contains _no_ values.
is_empty(&self) -> bool238     pub fn is_empty(&self) -> bool {
239         self.values.is_empty()
240     }
241 }
242 
243 // ===== impl Current =====
244 
245 impl Current {
246     /// Constructs a new `Current` that indicates the current context is a span
247     /// with the given `metadata` and `metadata`.
new(id: Id, metadata: &'static Metadata<'static>) -> Self248     pub fn new(id: Id, metadata: &'static Metadata<'static>) -> Self {
249         Self {
250             inner: CurrentInner::Current { id, metadata },
251         }
252     }
253 
254     /// Constructs a new `Current` that indicates the current context is *not*
255     /// in a span.
none() -> Self256     pub fn none() -> Self {
257         Self {
258             inner: CurrentInner::None,
259         }
260     }
261 
262     /// Constructs a new `Current` that indicates the `Subscriber` does not
263     /// track a current span.
unknown() -> Self264     pub(crate) fn unknown() -> Self {
265         Self {
266             inner: CurrentInner::Unknown,
267         }
268     }
269 
270     /// Returns `true` if the `Subscriber` that constructed this `Current` tracks a
271     /// current span.
272     ///
273     /// If this returns `true` and [`id`], [`metadata`], or [`into_inner`]
274     /// return `None`, that indicates that we are currently known to *not* be
275     /// inside a span. If this returns `false`, those methods will also return
276     /// `None`, but in this case, that is because the subscriber does not keep
277     /// track of the currently-entered span.
278     ///
279     /// [`id`]: #method.id
280     /// [`metadata`]: #method.metadata
281     /// [`into_inner`]: #method.into_inner
is_known(&self) -> bool282     pub fn is_known(&self) -> bool {
283         !matches!(self.inner, CurrentInner::Unknown)
284     }
285 
286     /// Consumes `self` and returns the span `Id` and `Metadata` of the current
287     /// span, if one exists and is known.
into_inner(self) -> Option<(Id, &'static Metadata<'static>)>288     pub fn into_inner(self) -> Option<(Id, &'static Metadata<'static>)> {
289         match self.inner {
290             CurrentInner::Current { id, metadata } => Some((id, metadata)),
291             _ => None,
292         }
293     }
294 
295     /// Borrows the `Id` of the current span, if one exists and is known.
id(&self) -> Option<&Id>296     pub fn id(&self) -> Option<&Id> {
297         match self.inner {
298             CurrentInner::Current { ref id, .. } => Some(id),
299             _ => None,
300         }
301     }
302 
303     /// Borrows the `Metadata` of the current span, if one exists and is known.
metadata(&self) -> Option<&'static Metadata<'static>>304     pub fn metadata(&self) -> Option<&'static Metadata<'static>> {
305         match self.inner {
306             CurrentInner::Current { ref metadata, .. } => Some(*metadata),
307             _ => None,
308         }
309     }
310 }
311 
312 impl<'a> From<&'a Current> for Option<&'a Id> {
from(cur: &'a Current) -> Self313     fn from(cur: &'a Current) -> Self {
314         cur.id()
315     }
316 }
317 
318 impl<'a> From<&'a Current> for Option<Id> {
from(cur: &'a Current) -> Self319     fn from(cur: &'a Current) -> Self {
320         cur.id().cloned()
321     }
322 }
323 
324 impl From<Current> for Option<Id> {
from(cur: Current) -> Self325     fn from(cur: Current) -> Self {
326         match cur.inner {
327             CurrentInner::Current { id, .. } => Some(id),
328             _ => None,
329         }
330     }
331 }
332 
333 impl<'a> From<&'a Current> for Option<&'static Metadata<'static>> {
from(cur: &'a Current) -> Self334     fn from(cur: &'a Current) -> Self {
335         cur.metadata()
336     }
337 }
338