• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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`]: super::subscriber::Subscriber
14 /// [`new_span`]: super::subscriber::Subscriber::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]: super::subscriber::Subscriber::current_span
42 /// [`Metadata`]: super::metadata::Metadata
43 #[derive(Debug)]
44 pub struct Current {
45     inner: CurrentInner,
46 }
47 
48 #[derive(Debug)]
49 enum CurrentInner {
50     Current {
51         id: Id,
52         metadata: &'static Metadata<'static>,
53     },
54     None,
55     Unknown,
56 }
57 
58 // ===== impl Span =====
59 
60 impl Id {
61     /// Constructs a new span ID from the given `u64`.
62     ///
63     /// <pre class="ignore" style="white-space:normal;font:inherit;">
64     ///     <strong>Note</strong>: Span IDs must be greater than zero.
65     /// </pre>
66     ///
67     /// # Panics
68     /// - If the provided `u64` is 0.
from_u64(u: u64) -> Self69     pub fn from_u64(u: u64) -> Self {
70         Id(NonZeroU64::new(u).expect("span IDs must be > 0"))
71     }
72 
73     /// Constructs a new span ID from the given `NonZeroU64`.
74     ///
75     /// Unlike [`Id::from_u64`](Id::from_u64()), this will never panic.
76     #[inline]
from_non_zero_u64(id: NonZeroU64) -> Self77     pub const fn from_non_zero_u64(id: NonZeroU64) -> Self {
78         Id(id)
79     }
80 
81     // Allow `into` by-ref since we don't want to impl Copy for Id
82     #[allow(clippy::wrong_self_convention)]
83     /// Returns the span's ID as a `u64`.
into_u64(&self) -> u6484     pub fn into_u64(&self) -> u64 {
85         self.0.get()
86     }
87 
88     // Allow `into` by-ref since we don't want to impl Copy for Id
89     #[allow(clippy::wrong_self_convention)]
90     /// Returns the span's ID as a `NonZeroU64`.
91     #[inline]
into_non_zero_u64(&self) -> NonZeroU6492     pub const fn into_non_zero_u64(&self) -> NonZeroU64 {
93         self.0
94     }
95 }
96 
97 impl<'a> From<&'a Id> for Option<Id> {
from(id: &'a Id) -> Self98     fn from(id: &'a Id) -> Self {
99         Some(id.clone())
100     }
101 }
102 
103 // ===== impl Attributes =====
104 
105 impl<'a> Attributes<'a> {
106     /// Returns `Attributes` describing a new child span of the current span,
107     /// with the provided metadata and values.
new(metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>) -> Self108     pub fn new(metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>) -> Self {
109         Attributes {
110             metadata,
111             values,
112             parent: Parent::Current,
113         }
114     }
115 
116     /// Returns `Attributes` describing a new span at the root of its own trace
117     /// tree, with the provided metadata and values.
new_root(metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>) -> Self118     pub fn new_root(metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>) -> Self {
119         Attributes {
120             metadata,
121             values,
122             parent: Parent::Root,
123         }
124     }
125 
126     /// Returns `Attributes` describing a new child span of the specified
127     /// parent span, with the provided metadata and values.
child_of( parent: Id, metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>, ) -> Self128     pub fn child_of(
129         parent: Id,
130         metadata: &'static Metadata<'static>,
131         values: &'a field::ValueSet<'a>,
132     ) -> Self {
133         Attributes {
134             metadata,
135             values,
136             parent: Parent::Explicit(parent),
137         }
138     }
139 
140     /// Returns a reference to the new span's metadata.
metadata(&self) -> &'static Metadata<'static>141     pub fn metadata(&self) -> &'static Metadata<'static> {
142         self.metadata
143     }
144 
145     /// Returns a reference to a `ValueSet` containing any values the new span
146     /// was created with.
values(&self) -> &field::ValueSet<'a>147     pub fn values(&self) -> &field::ValueSet<'a> {
148         self.values
149     }
150 
151     /// Returns true if the new span should be a root.
is_root(&self) -> bool152     pub fn is_root(&self) -> bool {
153         matches!(self.parent, Parent::Root)
154     }
155 
156     /// Returns true if the new span's parent should be determined based on the
157     /// current context.
158     ///
159     /// If this is true and the current thread is currently inside a span, then
160     /// that span should be the new span's parent. Otherwise, if the current
161     /// thread is _not_ inside a span, then the new span will be the root of its
162     /// own trace tree.
is_contextual(&self) -> bool163     pub fn is_contextual(&self) -> bool {
164         matches!(self.parent, Parent::Current)
165     }
166 
167     /// Returns the new span's explicitly-specified parent, if there is one.
168     ///
169     /// Otherwise (if the new span is a root or is a child of the current span),
170     /// returns `None`.
parent(&self) -> Option<&Id>171     pub fn parent(&self) -> Option<&Id> {
172         match self.parent {
173             Parent::Explicit(ref p) => Some(p),
174             _ => None,
175         }
176     }
177 
178     /// Records all the fields in this set of `Attributes` with the provided
179     /// [Visitor].
180     ///
181     /// [visitor]: super::field::Visit
record(&self, visitor: &mut dyn field::Visit)182     pub fn record(&self, visitor: &mut dyn field::Visit) {
183         self.values.record(visitor)
184     }
185 
186     /// Returns `true` if this set of `Attributes` contains a value for the
187     /// given `Field`.
contains(&self, field: &field::Field) -> bool188     pub fn contains(&self, field: &field::Field) -> bool {
189         self.values.contains(field)
190     }
191 
192     /// Returns true if this set of `Attributes` contains _no_ values.
is_empty(&self) -> bool193     pub fn is_empty(&self) -> bool {
194         self.values.is_empty()
195     }
196 
197     /// Returns the set of all [fields] defined by this span's [`Metadata`].
198     ///
199     /// Note that the [`FieldSet`] returned by this method includes *all* the
200     /// fields declared by this span, not just those with values that are recorded
201     /// as part of this set of `Attributes`. Other fields with values not present in
202     /// this `Attributes`' value set may [record] values later.
203     ///
204     /// [fields]: crate::field
205     /// [record]: Attributes::record()
206     /// [`Metadata`]: crate::metadata::Metadata
207     /// [`FieldSet`]: crate::field::FieldSet
fields(&self) -> &FieldSet208     pub fn fields(&self) -> &FieldSet {
209         self.values.field_set()
210     }
211 }
212 
213 // ===== impl Record =====
214 
215 impl<'a> Record<'a> {
216     /// Constructs a new `Record` from a `ValueSet`.
new(values: &'a field::ValueSet<'a>) -> Self217     pub fn new(values: &'a field::ValueSet<'a>) -> Self {
218         Self { values }
219     }
220 
221     /// Records all the fields in this `Record` with the provided [Visitor].
222     ///
223     /// [visitor]: super::field::Visit
record(&self, visitor: &mut dyn field::Visit)224     pub fn record(&self, visitor: &mut dyn field::Visit) {
225         self.values.record(visitor)
226     }
227 
228     /// Returns the number of fields that would be visited from this `Record`
229     /// when [`Record::record()`] is called
230     ///
231     /// [`Record::record()`]: Record::record()
len(&self) -> usize232     pub fn len(&self) -> usize {
233         self.values.len()
234     }
235 
236     /// Returns `true` if this `Record` contains a value for the given `Field`.
contains(&self, field: &field::Field) -> bool237     pub fn contains(&self, field: &field::Field) -> bool {
238         self.values.contains(field)
239     }
240 
241     /// Returns true if this `Record` contains _no_ values.
is_empty(&self) -> bool242     pub fn is_empty(&self) -> bool {
243         self.values.is_empty()
244     }
245 }
246 
247 // ===== impl Current =====
248 
249 impl Current {
250     /// Constructs a new `Current` that indicates the current context is a span
251     /// with the given `metadata` and `metadata`.
new(id: Id, metadata: &'static Metadata<'static>) -> Self252     pub fn new(id: Id, metadata: &'static Metadata<'static>) -> Self {
253         Self {
254             inner: CurrentInner::Current { id, metadata },
255         }
256     }
257 
258     /// Constructs a new `Current` that indicates the current context is *not*
259     /// in a span.
none() -> Self260     pub fn none() -> Self {
261         Self {
262             inner: CurrentInner::None,
263         }
264     }
265 
266     /// Constructs a new `Current` that indicates the `Subscriber` does not
267     /// track a current span.
unknown() -> Self268     pub(crate) fn unknown() -> Self {
269         Self {
270             inner: CurrentInner::Unknown,
271         }
272     }
273 
274     /// Returns `true` if the `Subscriber` that constructed this `Current` tracks a
275     /// current span.
276     ///
277     /// If this returns `true` and [`id`], [`metadata`], or [`into_inner`]
278     /// return `None`, that indicates that we are currently known to *not* be
279     /// inside a span. If this returns `false`, those methods will also return
280     /// `None`, but in this case, that is because the subscriber does not keep
281     /// track of the currently-entered span.
282     ///
283     /// [`id`]: Current::id()
284     /// [`metadata`]: Current::metadata()
285     /// [`into_inner`]: Current::into_inner()
is_known(&self) -> bool286     pub fn is_known(&self) -> bool {
287         !matches!(self.inner, CurrentInner::Unknown)
288     }
289 
290     /// Consumes `self` and returns the span `Id` and `Metadata` of the current
291     /// span, if one exists and is known.
into_inner(self) -> Option<(Id, &'static Metadata<'static>)>292     pub fn into_inner(self) -> Option<(Id, &'static Metadata<'static>)> {
293         match self.inner {
294             CurrentInner::Current { id, metadata } => Some((id, metadata)),
295             _ => None,
296         }
297     }
298 
299     /// Borrows the `Id` of the current span, if one exists and is known.
id(&self) -> Option<&Id>300     pub fn id(&self) -> Option<&Id> {
301         match self.inner {
302             CurrentInner::Current { ref id, .. } => Some(id),
303             _ => None,
304         }
305     }
306 
307     /// Borrows the `Metadata` of the current span, if one exists and is known.
metadata(&self) -> Option<&'static Metadata<'static>>308     pub fn metadata(&self) -> Option<&'static Metadata<'static>> {
309         match self.inner {
310             CurrentInner::Current { metadata, .. } => Some(metadata),
311             _ => None,
312         }
313     }
314 }
315 
316 impl<'a> From<&'a Current> for Option<&'a Id> {
from(cur: &'a Current) -> Self317     fn from(cur: &'a Current) -> Self {
318         cur.id()
319     }
320 }
321 
322 impl<'a> From<&'a Current> for Option<Id> {
from(cur: &'a Current) -> Self323     fn from(cur: &'a Current) -> Self {
324         cur.id().cloned()
325     }
326 }
327 
328 impl From<Current> for Option<Id> {
from(cur: Current) -> Self329     fn from(cur: Current) -> Self {
330         match cur.inner {
331             CurrentInner::Current { id, .. } => Some(id),
332             _ => None,
333         }
334     }
335 }
336 
337 impl<'a> From<&'a Current> for Option<&'static Metadata<'static>> {
from(cur: &'a Current) -> Self338     fn from(cur: &'a Current) -> Self {
339         cur.metadata()
340     }
341 }
342