1 | use super::*; |
2 | use tracing_core::subscriber::NoSubscriber; |
3 | |
4 | #[derive(Debug)] |
5 | pub(crate) struct NopLayer; |
6 | impl<S: Subscriber> Layer<S> for NopLayer {} |
7 | |
8 | #[allow (dead_code)] |
9 | struct NopLayer2; |
10 | impl<S: Subscriber> Layer<S> for NopLayer2 {} |
11 | |
12 | /// A layer that holds a string. |
13 | /// |
14 | /// Used to test that pointers returned by downcasting are actually valid. |
15 | struct StringLayer(&'static str); |
16 | impl<S: Subscriber> Layer<S> for StringLayer {} |
17 | struct StringLayer2(&'static str); |
18 | impl<S: Subscriber> Layer<S> for StringLayer2 {} |
19 | |
20 | struct StringLayer3(&'static str); |
21 | impl<S: Subscriber> Layer<S> for StringLayer3 {} |
22 | |
23 | pub(crate) struct StringSubscriber(&'static str); |
24 | |
25 | impl Subscriber for StringSubscriber { |
26 | fn register_callsite(&self, _: &'static Metadata<'static>) -> Interest { |
27 | Interest::never() |
28 | } |
29 | |
30 | fn enabled(&self, _: &Metadata<'_>) -> bool { |
31 | false |
32 | } |
33 | |
34 | fn new_span(&self, _: &span::Attributes<'_>) -> span::Id { |
35 | span::Id::from_u64(1) |
36 | } |
37 | |
38 | fn record(&self, _: &span::Id, _: &span::Record<'_>) {} |
39 | fn record_follows_from(&self, _: &span::Id, _: &span::Id) {} |
40 | fn event(&self, _: &Event<'_>) {} |
41 | fn enter(&self, _: &span::Id) {} |
42 | fn exit(&self, _: &span::Id) {} |
43 | } |
44 | |
45 | fn assert_subscriber(_s: impl Subscriber) {} |
46 | fn assert_layer<S: Subscriber>(_l: &impl Layer<S>) {} |
47 | |
48 | #[test] |
49 | fn layer_is_subscriber() { |
50 | let s = NopLayer.with_subscriber(NoSubscriber::default()); |
51 | assert_subscriber(s) |
52 | } |
53 | |
54 | #[test] |
55 | fn two_layers_are_subscriber() { |
56 | let s = NopLayer |
57 | .and_then(NopLayer) |
58 | .with_subscriber(NoSubscriber::default()); |
59 | assert_subscriber(s) |
60 | } |
61 | |
62 | #[test] |
63 | fn three_layers_are_subscriber() { |
64 | let s = NopLayer |
65 | .and_then(NopLayer) |
66 | .and_then(NopLayer) |
67 | .with_subscriber(NoSubscriber::default()); |
68 | assert_subscriber(s) |
69 | } |
70 | |
71 | #[test] |
72 | fn three_layers_are_layer() { |
73 | let layers = NopLayer.and_then(NopLayer).and_then(NopLayer); |
74 | assert_layer(&layers); |
75 | let _ = layers.with_subscriber(NoSubscriber::default()); |
76 | } |
77 | |
78 | #[test] |
79 | #[cfg (feature = "alloc" )] |
80 | fn box_layer_is_layer() { |
81 | use alloc::boxed::Box; |
82 | let l: Box<dyn Layer<NoSubscriber> + Send + Sync> = Box::new(NopLayer); |
83 | assert_layer(&l); |
84 | l.with_subscriber(NoSubscriber::default()); |
85 | } |
86 | |
87 | #[test] |
88 | fn downcasts_to_subscriber() { |
89 | let s = NopLayer |
90 | .and_then(NopLayer) |
91 | .and_then(NopLayer) |
92 | .with_subscriber(StringSubscriber("subscriber" )); |
93 | let subscriber = |
94 | <dyn Subscriber>::downcast_ref::<StringSubscriber>(&s).expect("subscriber should downcast" ); |
95 | assert_eq!(subscriber.0, "subscriber" ); |
96 | } |
97 | |
98 | #[test] |
99 | fn downcasts_to_layer() { |
100 | let s = StringLayer("layer_1" ) |
101 | .and_then(StringLayer2("layer_2" )) |
102 | .and_then(StringLayer3("layer_3" )) |
103 | .with_subscriber(NoSubscriber::default()); |
104 | let layer = <dyn Subscriber>::downcast_ref::<StringLayer>(&s).expect("layer 1 should downcast" ); |
105 | assert_eq!(layer.0, "layer_1" ); |
106 | let layer = |
107 | <dyn Subscriber>::downcast_ref::<StringLayer2>(&s).expect("layer 2 should downcast" ); |
108 | assert_eq!(layer.0, "layer_2" ); |
109 | let layer = |
110 | <dyn Subscriber>::downcast_ref::<StringLayer3>(&s).expect("layer 3 should downcast" ); |
111 | assert_eq!(layer.0, "layer_3" ); |
112 | } |
113 | |
114 | #[cfg (all(feature = "registry" , feature = "std" ))] |
115 | mod registry_tests { |
116 | use super::*; |
117 | use crate::registry::LookupSpan; |
118 | |
119 | #[test] |
120 | fn context_event_span() { |
121 | use std::sync::{Arc, Mutex}; |
122 | let last_event_span = Arc::new(Mutex::new(None)); |
123 | |
124 | struct RecordingLayer { |
125 | last_event_span: Arc<Mutex<Option<&'static str>>>, |
126 | } |
127 | |
128 | impl<S> Layer<S> for RecordingLayer |
129 | where |
130 | S: Subscriber + for<'lookup> LookupSpan<'lookup>, |
131 | { |
132 | fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) { |
133 | let span = ctx.event_span(event); |
134 | *self.last_event_span.lock().unwrap() = span.map(|s| s.name()); |
135 | } |
136 | } |
137 | |
138 | tracing::subscriber::with_default( |
139 | crate::registry().with(RecordingLayer { |
140 | last_event_span: last_event_span.clone(), |
141 | }), |
142 | || { |
143 | tracing::info!("no span" ); |
144 | assert_eq!(*last_event_span.lock().unwrap(), None); |
145 | |
146 | let parent = tracing::info_span!("explicit" ); |
147 | tracing::info!(parent: &parent, "explicit span" ); |
148 | assert_eq!(*last_event_span.lock().unwrap(), Some("explicit" )); |
149 | |
150 | let _guard = tracing::info_span!("contextual" ).entered(); |
151 | tracing::info!("contextual span" ); |
152 | assert_eq!(*last_event_span.lock().unwrap(), Some("contextual" )); |
153 | }, |
154 | ); |
155 | } |
156 | |
157 | /// Tests for how max-level hints are calculated when combining layers |
158 | /// with and without per-layer filtering. |
159 | mod max_level_hints { |
160 | |
161 | use super::*; |
162 | use crate::filter::*; |
163 | |
164 | #[test] |
165 | fn mixed_with_unfiltered() { |
166 | let subscriber = crate::registry() |
167 | .with(NopLayer) |
168 | .with(NopLayer.with_filter(LevelFilter::INFO)); |
169 | assert_eq!(subscriber.max_level_hint(), None); |
170 | } |
171 | |
172 | #[test] |
173 | fn mixed_with_unfiltered_layered() { |
174 | let subscriber = crate::registry().with(NopLayer).with( |
175 | NopLayer |
176 | .with_filter(LevelFilter::INFO) |
177 | .and_then(NopLayer.with_filter(LevelFilter::TRACE)), |
178 | ); |
179 | assert_eq!(dbg!(subscriber).max_level_hint(), None); |
180 | } |
181 | |
182 | #[test] |
183 | fn mixed_interleaved() { |
184 | let subscriber = crate::registry() |
185 | .with(NopLayer) |
186 | .with(NopLayer.with_filter(LevelFilter::INFO)) |
187 | .with(NopLayer) |
188 | .with(NopLayer.with_filter(LevelFilter::INFO)); |
189 | assert_eq!(dbg!(subscriber).max_level_hint(), None); |
190 | } |
191 | |
192 | #[test] |
193 | fn mixed_layered() { |
194 | let subscriber = crate::registry() |
195 | .with(NopLayer.with_filter(LevelFilter::INFO).and_then(NopLayer)) |
196 | .with(NopLayer.and_then(NopLayer.with_filter(LevelFilter::INFO))); |
197 | assert_eq!(dbg!(subscriber).max_level_hint(), None); |
198 | } |
199 | |
200 | #[test] |
201 | fn plf_only_unhinted() { |
202 | let subscriber = crate::registry() |
203 | .with(NopLayer.with_filter(LevelFilter::INFO)) |
204 | .with(NopLayer.with_filter(filter_fn(|_| true))); |
205 | assert_eq!(dbg!(subscriber).max_level_hint(), None); |
206 | } |
207 | |
208 | #[test] |
209 | fn plf_only_unhinted_nested_outer() { |
210 | // if a nested tree of per-layer filters has an _outer_ filter with |
211 | // no max level hint, it should return `None`. |
212 | let subscriber = crate::registry() |
213 | .with( |
214 | NopLayer |
215 | .with_filter(LevelFilter::INFO) |
216 | .and_then(NopLayer.with_filter(LevelFilter::WARN)), |
217 | ) |
218 | .with( |
219 | NopLayer |
220 | .with_filter(filter_fn(|_| true)) |
221 | .and_then(NopLayer.with_filter(LevelFilter::DEBUG)), |
222 | ); |
223 | assert_eq!(dbg!(subscriber).max_level_hint(), None); |
224 | } |
225 | |
226 | #[test] |
227 | fn plf_only_unhinted_nested_inner() { |
228 | // If a nested tree of per-layer filters has an _inner_ filter with |
229 | // no max-level hint, but the _outer_ filter has a max level hint, |
230 | // it should pick the outer hint. This is because the outer filter |
231 | // will disable the spans/events before they make it to the inner |
232 | // filter. |
233 | let subscriber = dbg!(crate::registry().with( |
234 | NopLayer |
235 | .with_filter(filter_fn(|_| true)) |
236 | .and_then(NopLayer.with_filter(filter_fn(|_| true))) |
237 | .with_filter(LevelFilter::INFO), |
238 | )); |
239 | assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::INFO)); |
240 | } |
241 | |
242 | #[test] |
243 | fn unhinted_nested_inner() { |
244 | let subscriber = dbg!(crate::registry() |
245 | .with(NopLayer.and_then(NopLayer).with_filter(LevelFilter::INFO)) |
246 | .with( |
247 | NopLayer |
248 | .with_filter(filter_fn(|_| true)) |
249 | .and_then(NopLayer.with_filter(filter_fn(|_| true))) |
250 | .with_filter(LevelFilter::WARN), |
251 | )); |
252 | assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::INFO)); |
253 | } |
254 | |
255 | #[test] |
256 | fn unhinted_nested_inner_mixed() { |
257 | let subscriber = dbg!(crate::registry() |
258 | .with( |
259 | NopLayer |
260 | .and_then(NopLayer.with_filter(filter_fn(|_| true))) |
261 | .with_filter(LevelFilter::INFO) |
262 | ) |
263 | .with( |
264 | NopLayer |
265 | .with_filter(filter_fn(|_| true)) |
266 | .and_then(NopLayer.with_filter(filter_fn(|_| true))) |
267 | .with_filter(LevelFilter::WARN), |
268 | )); |
269 | assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::INFO)); |
270 | } |
271 | |
272 | #[test] |
273 | fn plf_only_picks_max() { |
274 | let subscriber = crate::registry() |
275 | .with(NopLayer.with_filter(LevelFilter::WARN)) |
276 | .with(NopLayer.with_filter(LevelFilter::DEBUG)); |
277 | assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::DEBUG)); |
278 | } |
279 | |
280 | #[test] |
281 | fn many_plf_only_picks_max() { |
282 | let subscriber = crate::registry() |
283 | .with(NopLayer.with_filter(LevelFilter::WARN)) |
284 | .with(NopLayer.with_filter(LevelFilter::DEBUG)) |
285 | .with(NopLayer.with_filter(LevelFilter::INFO)) |
286 | .with(NopLayer.with_filter(LevelFilter::ERROR)); |
287 | assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::DEBUG)); |
288 | } |
289 | |
290 | #[test] |
291 | fn nested_plf_only_picks_max() { |
292 | let subscriber = crate::registry() |
293 | .with( |
294 | NopLayer.with_filter(LevelFilter::INFO).and_then( |
295 | NopLayer |
296 | .with_filter(LevelFilter::WARN) |
297 | .and_then(NopLayer.with_filter(LevelFilter::DEBUG)), |
298 | ), |
299 | ) |
300 | .with( |
301 | NopLayer |
302 | .with_filter(LevelFilter::INFO) |
303 | .and_then(NopLayer.with_filter(LevelFilter::ERROR)), |
304 | ); |
305 | assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::DEBUG)); |
306 | } |
307 | } |
308 | } |
309 | |