1 | #![cfg (feature = "registry" )] |
2 | use std::{ |
3 | collections::HashMap, |
4 | sync::{Arc, Mutex}, |
5 | }; |
6 | use tracing::{Level, Subscriber}; |
7 | use tracing_mock::{layer::MockLayer, *}; |
8 | use tracing_subscriber::{filter, prelude::*}; |
9 | |
10 | #[test] |
11 | fn vec_layer_filter_interests_are_cached() { |
12 | let mk_filtered = |level: Level, subscriber: MockLayer| { |
13 | let seen = Arc::new(Mutex::new(HashMap::new())); |
14 | let filter = filter::filter_fn({ |
15 | let seen = seen.clone(); |
16 | move |meta| { |
17 | *seen.lock().unwrap().entry(*meta.level()).or_insert(0usize) += 1; |
18 | meta.level() <= &level |
19 | } |
20 | }); |
21 | (subscriber.with_filter(filter).boxed(), seen) |
22 | }; |
23 | |
24 | // This layer will return Interest::always for INFO and lower. |
25 | let (info_layer, info_handle) = layer::named("info" ) |
26 | .event(expect::event().at_level(Level::INFO)) |
27 | .event(expect::event().at_level(Level::WARN)) |
28 | .event(expect::event().at_level(Level::ERROR)) |
29 | .event(expect::event().at_level(Level::INFO)) |
30 | .event(expect::event().at_level(Level::WARN)) |
31 | .event(expect::event().at_level(Level::ERROR)) |
32 | .only() |
33 | .run_with_handle(); |
34 | let (info_layer, seen_info) = mk_filtered(Level::INFO, info_layer); |
35 | |
36 | // This layer will return Interest::always for WARN and lower. |
37 | let (warn_layer, warn_handle) = layer::named("warn" ) |
38 | .event(expect::event().at_level(Level::WARN)) |
39 | .event(expect::event().at_level(Level::ERROR)) |
40 | .event(expect::event().at_level(Level::WARN)) |
41 | .event(expect::event().at_level(Level::ERROR)) |
42 | .only() |
43 | .run_with_handle(); |
44 | let (warn_layer, seen_warn) = mk_filtered(Level::WARN, warn_layer); |
45 | |
46 | let subscriber = tracing_subscriber::registry().with(vec![warn_layer, info_layer]); |
47 | assert!(subscriber.max_level_hint().is_none()); |
48 | |
49 | let _subscriber = subscriber.set_default(); |
50 | |
51 | fn events() { |
52 | tracing::trace!("hello trace" ); |
53 | tracing::debug!("hello debug" ); |
54 | tracing::info!("hello info" ); |
55 | tracing::warn!("hello warn" ); |
56 | tracing::error!("hello error" ); |
57 | } |
58 | |
59 | events(); |
60 | { |
61 | let lock = seen_info.lock().unwrap(); |
62 | for (&level, &count) in lock.iter() { |
63 | if level == Level::INFO { |
64 | continue; |
65 | } |
66 | assert_eq!( |
67 | count, 1, |
68 | "level {:?} should have been seen 1 time by the INFO subscriber (after first set of events)" , |
69 | level |
70 | ); |
71 | } |
72 | |
73 | let lock = seen_warn.lock().unwrap(); |
74 | for (&level, &count) in lock.iter() { |
75 | if level == Level::INFO { |
76 | continue; |
77 | } |
78 | assert_eq!( |
79 | count, 1, |
80 | "level {:?} should have been seen 1 time by the WARN subscriber (after first set of events)" , |
81 | level |
82 | ); |
83 | } |
84 | } |
85 | |
86 | events(); |
87 | { |
88 | let lock = seen_info.lock().unwrap(); |
89 | for (&level, &count) in lock.iter() { |
90 | if level == Level::INFO { |
91 | continue; |
92 | } |
93 | assert_eq!( |
94 | count, 1, |
95 | "level {:?} should have been seen 1 time by the INFO subscriber (after second set of events)" , |
96 | level |
97 | ); |
98 | } |
99 | |
100 | let lock = seen_warn.lock().unwrap(); |
101 | for (&level, &count) in lock.iter() { |
102 | if level == Level::INFO { |
103 | continue; |
104 | } |
105 | assert_eq!( |
106 | count, 1, |
107 | "level {:?} should have been seen 1 time by the WARN subscriber (after second set of events)" , |
108 | level |
109 | ); |
110 | } |
111 | } |
112 | |
113 | info_handle.assert_finished(); |
114 | warn_handle.assert_finished(); |
115 | } |
116 | |