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