• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![allow(missing_docs)]
2 use super::{field, metadata, Parent};
3 use std::fmt;
4 
5 /// A mock span.
6 ///
7 /// This is intended for use with the mock subscriber API in the
8 /// `subscriber` module.
9 #[derive(Clone, Default, Eq, PartialEq)]
10 pub struct MockSpan {
11     pub(crate) metadata: metadata::Expect,
12 }
13 
14 #[derive(Default, Eq, PartialEq)]
15 pub struct NewSpan {
16     pub(crate) span: MockSpan,
17     pub(crate) fields: field::Expect,
18     pub(crate) parent: Option<Parent>,
19 }
20 
mock() -> MockSpan21 pub fn mock() -> MockSpan {
22     MockSpan {
23         ..Default::default()
24     }
25 }
26 
named<I>(name: I) -> MockSpan where I: Into<String>,27 pub fn named<I>(name: I) -> MockSpan
28 where
29     I: Into<String>,
30 {
31     mock().named(name)
32 }
33 
34 impl MockSpan {
named<I>(self, name: I) -> Self where I: Into<String>,35     pub fn named<I>(self, name: I) -> Self
36     where
37         I: Into<String>,
38     {
39         Self {
40             metadata: metadata::Expect {
41                 name: Some(name.into()),
42                 ..self.metadata
43             },
44         }
45     }
46 
at_level(self, level: tracing::Level) -> Self47     pub fn at_level(self, level: tracing::Level) -> Self {
48         Self {
49             metadata: metadata::Expect {
50                 level: Some(level),
51                 ..self.metadata
52             },
53         }
54     }
55 
with_target<I>(self, target: I) -> Self where I: Into<String>,56     pub fn with_target<I>(self, target: I) -> Self
57     where
58         I: Into<String>,
59     {
60         Self {
61             metadata: metadata::Expect {
62                 target: Some(target.into()),
63                 ..self.metadata
64             },
65         }
66     }
67 
with_explicit_parent(self, parent: Option<&str>) -> NewSpan68     pub fn with_explicit_parent(self, parent: Option<&str>) -> NewSpan {
69         let parent = match parent {
70             Some(name) => Parent::Explicit(name.into()),
71             None => Parent::ExplicitRoot,
72         };
73         NewSpan {
74             parent: Some(parent),
75             span: self,
76             ..Default::default()
77         }
78     }
79 
with_contextual_parent(self, parent: Option<&str>) -> NewSpan80     pub fn with_contextual_parent(self, parent: Option<&str>) -> NewSpan {
81         let parent = match parent {
82             Some(name) => Parent::Contextual(name.into()),
83             None => Parent::ContextualRoot,
84         };
85         NewSpan {
86             parent: Some(parent),
87             span: self,
88             ..Default::default()
89         }
90     }
91 
name(&self) -> Option<&str>92     pub fn name(&self) -> Option<&str> {
93         self.metadata.name.as_ref().map(String::as_ref)
94     }
95 
level(&self) -> Option<tracing::Level>96     pub fn level(&self) -> Option<tracing::Level> {
97         self.metadata.level
98     }
99 
target(&self) -> Option<&str>100     pub fn target(&self) -> Option<&str> {
101         self.metadata.target.as_deref()
102     }
103 
with_field<I>(self, fields: I) -> NewSpan where I: Into<field::Expect>,104     pub fn with_field<I>(self, fields: I) -> NewSpan
105     where
106         I: Into<field::Expect>,
107     {
108         NewSpan {
109             span: self,
110             fields: fields.into(),
111             ..Default::default()
112         }
113     }
114 }
115 
116 impl fmt::Debug for MockSpan {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result117     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118         let mut s = f.debug_struct("MockSpan");
119 
120         if let Some(name) = self.name() {
121             s.field("name", &name);
122         }
123 
124         if let Some(level) = self.level() {
125             s.field("level", &format_args!("{:?}", level));
126         }
127 
128         if let Some(target) = self.target() {
129             s.field("target", &target);
130         }
131 
132         s.finish()
133     }
134 }
135 
136 impl fmt::Display for MockSpan {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result137     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138         if self.metadata.name.is_some() {
139             write!(f, "a span{}", self.metadata)
140         } else {
141             write!(f, "any span{}", self.metadata)
142         }
143     }
144 }
145 
146 impl From<MockSpan> for NewSpan {
from(span: MockSpan) -> Self147     fn from(span: MockSpan) -> Self {
148         Self {
149             span,
150             ..Default::default()
151         }
152     }
153 }
154 
155 impl NewSpan {
with_explicit_parent(self, parent: Option<&str>) -> NewSpan156     pub fn with_explicit_parent(self, parent: Option<&str>) -> NewSpan {
157         let parent = match parent {
158             Some(name) => Parent::Explicit(name.into()),
159             None => Parent::ExplicitRoot,
160         };
161         NewSpan {
162             parent: Some(parent),
163             ..self
164         }
165     }
166 
with_contextual_parent(self, parent: Option<&str>) -> NewSpan167     pub fn with_contextual_parent(self, parent: Option<&str>) -> NewSpan {
168         let parent = match parent {
169             Some(name) => Parent::Contextual(name.into()),
170             None => Parent::ContextualRoot,
171         };
172         NewSpan {
173             parent: Some(parent),
174             ..self
175         }
176     }
177 
with_field<I>(self, fields: I) -> NewSpan where I: Into<field::Expect>,178     pub fn with_field<I>(self, fields: I) -> NewSpan
179     where
180         I: Into<field::Expect>,
181     {
182         NewSpan {
183             fields: fields.into(),
184             ..self
185         }
186     }
187 
check( &mut self, span: &tracing_core::span::Attributes<'_>, get_parent_name: impl FnOnce() -> Option<String>, subscriber_name: &str, )188     pub fn check(
189         &mut self,
190         span: &tracing_core::span::Attributes<'_>,
191         get_parent_name: impl FnOnce() -> Option<String>,
192         subscriber_name: &str,
193     ) {
194         let meta = span.metadata();
195         let name = meta.name();
196         self.span
197             .metadata
198             .check(meta, format_args!("span `{}`", name), subscriber_name);
199         let mut checker = self.fields.checker(name, subscriber_name);
200         span.record(&mut checker);
201         checker.finish();
202 
203         if let Some(expected_parent) = self.parent.as_ref() {
204             let actual_parent = get_parent_name();
205             expected_parent.check_parent_name(
206                 actual_parent.as_deref(),
207                 span.parent().cloned(),
208                 format_args!("span `{}`", name),
209                 subscriber_name,
210             )
211         }
212     }
213 }
214 
215 impl fmt::Display for NewSpan {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result216     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217         write!(f, "a new span{}", self.span.metadata)?;
218         if !self.fields.is_empty() {
219             write!(f, " with {}", self.fields)?;
220         }
221         Ok(())
222     }
223 }
224 
225 impl fmt::Debug for NewSpan {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result226     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227         let mut s = f.debug_struct("NewSpan");
228 
229         if let Some(name) = self.span.name() {
230             s.field("name", &name);
231         }
232 
233         if let Some(level) = self.span.level() {
234             s.field("level", &format_args!("{:?}", level));
235         }
236 
237         if let Some(target) = self.span.target() {
238             s.field("target", &target);
239         }
240 
241         if let Some(ref parent) = self.parent {
242             s.field("parent", &format_args!("{:?}", parent));
243         }
244 
245         if !self.fields.is_empty() {
246             s.field("fields", &self.fields);
247         }
248 
249         s.finish()
250     }
251 }
252