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}