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