1 | #![cfg (feature = "registry" )] |
2 | use std::sync::atomic::{AtomicUsize, Ordering}; |
3 | use tracing_core::{ |
4 | span::{Attributes, Id, Record}, |
5 | subscriber::Interest, |
6 | Event, LevelFilter, Metadata, Subscriber, |
7 | }; |
8 | use tracing_subscriber::{layer, prelude::*, reload::*}; |
9 | |
10 | pub struct NopSubscriber; |
11 | fn event() { |
12 | tracing::info!("my event" ); |
13 | } |
14 | |
15 | impl Subscriber for NopSubscriber { |
16 | fn register_callsite(&self, _: &'static Metadata<'static>) -> Interest { |
17 | Interest::never() |
18 | } |
19 | |
20 | fn enabled(&self, _: &Metadata<'_>) -> bool { |
21 | false |
22 | } |
23 | |
24 | fn new_span(&self, _: &Attributes<'_>) -> Id { |
25 | Id::from_u64(1) |
26 | } |
27 | |
28 | fn record(&self, _: &Id, _: &Record<'_>) {} |
29 | fn record_follows_from(&self, _: &Id, _: &Id) {} |
30 | fn event(&self, _: &Event<'_>) {} |
31 | fn enter(&self, _: &Id) {} |
32 | fn exit(&self, _: &Id) {} |
33 | } |
34 | |
35 | #[test] |
36 | fn reload_handle() { |
37 | static FILTER1_CALLS: AtomicUsize = AtomicUsize::new(0); |
38 | static FILTER2_CALLS: AtomicUsize = AtomicUsize::new(0); |
39 | |
40 | enum Filter { |
41 | One, |
42 | Two, |
43 | } |
44 | |
45 | impl<S: Subscriber> tracing_subscriber::Layer<S> for Filter { |
46 | fn register_callsite(&self, m: &Metadata<'_>) -> Interest { |
47 | println!("REGISTER: {:?}" , m); |
48 | Interest::sometimes() |
49 | } |
50 | |
51 | fn enabled(&self, m: &Metadata<'_>, _: layer::Context<'_, S>) -> bool { |
52 | println!("ENABLED: {:?}" , m); |
53 | match self { |
54 | Filter::One => FILTER1_CALLS.fetch_add(1, Ordering::SeqCst), |
55 | Filter::Two => FILTER2_CALLS.fetch_add(1, Ordering::SeqCst), |
56 | }; |
57 | true |
58 | } |
59 | |
60 | fn max_level_hint(&self) -> Option<LevelFilter> { |
61 | match self { |
62 | Filter::One => Some(LevelFilter::INFO), |
63 | Filter::Two => Some(LevelFilter::DEBUG), |
64 | } |
65 | } |
66 | } |
67 | |
68 | let (layer, handle) = Layer::new(Filter::One); |
69 | |
70 | let subscriber = tracing_core::dispatcher::Dispatch::new(layer.with_subscriber(NopSubscriber)); |
71 | |
72 | tracing_core::dispatcher::with_default(&subscriber, || { |
73 | assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 0); |
74 | assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 0); |
75 | |
76 | event(); |
77 | |
78 | assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1); |
79 | assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 0); |
80 | |
81 | assert_eq!(LevelFilter::current(), LevelFilter::INFO); |
82 | handle.reload(Filter::Two).expect("should reload" ); |
83 | assert_eq!(LevelFilter::current(), LevelFilter::DEBUG); |
84 | |
85 | event(); |
86 | |
87 | assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1); |
88 | assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 1); |
89 | }) |
90 | } |
91 | |
92 | #[test] |
93 | fn reload_filter() { |
94 | struct NopLayer; |
95 | impl<S: Subscriber> tracing_subscriber::Layer<S> for NopLayer { |
96 | fn register_callsite(&self, _m: &Metadata<'_>) -> Interest { |
97 | Interest::sometimes() |
98 | } |
99 | |
100 | fn enabled(&self, _m: &Metadata<'_>, _: layer::Context<'_, S>) -> bool { |
101 | true |
102 | } |
103 | } |
104 | |
105 | static FILTER1_CALLS: AtomicUsize = AtomicUsize::new(0); |
106 | static FILTER2_CALLS: AtomicUsize = AtomicUsize::new(0); |
107 | |
108 | enum Filter { |
109 | One, |
110 | Two, |
111 | } |
112 | |
113 | impl<S: Subscriber> tracing_subscriber::layer::Filter<S> for Filter { |
114 | fn enabled(&self, m: &Metadata<'_>, _: &layer::Context<'_, S>) -> bool { |
115 | println!("ENABLED: {:?}" , m); |
116 | match self { |
117 | Filter::One => FILTER1_CALLS.fetch_add(1, Ordering::SeqCst), |
118 | Filter::Two => FILTER2_CALLS.fetch_add(1, Ordering::SeqCst), |
119 | }; |
120 | true |
121 | } |
122 | |
123 | fn max_level_hint(&self) -> Option<LevelFilter> { |
124 | match self { |
125 | Filter::One => Some(LevelFilter::INFO), |
126 | Filter::Two => Some(LevelFilter::DEBUG), |
127 | } |
128 | } |
129 | } |
130 | |
131 | let (filter, handle) = Layer::new(Filter::One); |
132 | |
133 | let dispatcher = tracing_core::Dispatch::new( |
134 | tracing_subscriber::registry().with(NopLayer.with_filter(filter)), |
135 | ); |
136 | |
137 | tracing_core::dispatcher::with_default(&dispatcher, || { |
138 | assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 0); |
139 | assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 0); |
140 | |
141 | event(); |
142 | |
143 | assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1); |
144 | assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 0); |
145 | |
146 | assert_eq!(LevelFilter::current(), LevelFilter::INFO); |
147 | handle.reload(Filter::Two).expect("should reload" ); |
148 | assert_eq!(LevelFilter::current(), LevelFilter::DEBUG); |
149 | |
150 | event(); |
151 | |
152 | assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1); |
153 | assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 1); |
154 | }) |
155 | } |
156 | |