1#![cfg(feature = "registry")]
2use std::sync::atomic::{AtomicUsize, Ordering};
3use tracing_core::{
4 span::{Attributes, Id, Record},
5 subscriber::Interest,
6 Event, LevelFilter, Metadata, Subscriber,
7};
8use tracing_subscriber::{layer, prelude::*, reload::*};
9
10pub struct NopSubscriber;
11fn event() {
12 tracing::info!("my event");
13}
14
15impl 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]
36fn 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]
93fn 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