1#![cfg_attr(not(feature = "metrics"), no_std)]
19
20#[cfg(feature = "tracing")]
23pub use tracing::{debug, debug_span, error, info, info_span, trace, trace_span, warn};
24
25#[doc(hidden)]
60#[cfg(not(feature = "tracing"))]
61#[macro_export]
62macro_rules! __hick_trace_noop {
63 (target: $tgt:expr, $($rest:tt)*) => {
64 { if false { let _ = &$tgt; } $crate::__hick_trace_noop!($($rest)*) }
65 };
66
67 ($key:ident = %$val:expr, $($rest:tt)*) => {
68 { if false { let _ = &$val; } $crate::__hick_trace_noop!($($rest)*) }
69 };
70 ($key:ident = %$val:expr) => {
71 { if false { let _ = &$val; } }
72 };
73
74 ($key:ident = ?$val:expr, $($rest:tt)*) => {
75 { if false { let _ = &$val; } $crate::__hick_trace_noop!($($rest)*) }
76 };
77 ($key:ident = ?$val:expr) => {
78 { if false { let _ = &$val; } }
79 };
80
81 ($key:ident = $val:expr, $($rest:tt)*) => {
82 { if false { let _ = &$val; } $crate::__hick_trace_noop!($($rest)*) }
83 };
84 ($key:ident = $val:expr) => {
85 { if false { let _ = &$val; } }
86 };
87
88 ($key:ident, $($rest:tt)*) => {
91 { if false { let _ = &$key; } $crate::__hick_trace_noop!($($rest)*) }
92 };
93 ($key:ident) => {
94 { if false { let _ = &$key; } }
95 };
96
97 (%$val:expr, $($rest:tt)*) => {
99 { if false { let _ = &$val; } $crate::__hick_trace_noop!($($rest)*) }
100 };
101 (%$val:expr) => {
102 { if false { let _ = &$val; } }
103 };
104
105 (?$val:expr, $($rest:tt)*) => {
106 { if false { let _ = &$val; } $crate::__hick_trace_noop!($($rest)*) }
107 };
108 (?$val:expr) => {
109 { if false { let _ = &$val; } }
110 };
111
112 ($fmt:literal $(, $arg:expr)* $(,)?) => {
113 { if false { let _ = ::core::format_args!($fmt $(, $arg)*); } }
114 };
115
116 () => {{}};
117}
118
119#[cfg(not(feature = "tracing"))]
120pub use __hick_trace_noop as trace;
121#[cfg(not(feature = "tracing"))]
122pub use __hick_trace_noop as debug;
123#[cfg(not(feature = "tracing"))]
124pub use __hick_trace_noop as info;
125#[cfg(not(feature = "tracing"))]
126pub use __hick_trace_noop as warn;
127#[cfg(not(feature = "tracing"))]
128pub use __hick_trace_noop as error;
129
130#[cfg(not(feature = "tracing"))]
136#[derive(Debug)]
137pub struct NoopSpan;
138
139#[cfg(not(feature = "tracing"))]
140impl NoopSpan {
141 #[inline]
143 pub fn entered(self) -> Self {
144 self
145 }
146 #[inline]
148 pub fn enter(&self) -> Self {
149 NoopSpan
150 }
151}
152
153#[doc(hidden)]
159#[cfg(not(feature = "tracing"))]
160#[macro_export]
161macro_rules! __hick_trace_noop_span {
162 (target: $tgt:expr, $($rest:tt)*) => {
164 { if false { let _ = &$tgt; } $crate::__hick_trace_noop_span!($($rest)*) }
165 };
166
167 ($name:literal, $($fields:tt)*) => {
171 { $crate::__hick_trace_noop!($($fields)*); $crate::NoopSpan }
172 };
173 ($name:literal) => {
174 $crate::NoopSpan
175 };
176
177 ($($tt:tt)*) => {
179 { $crate::__hick_trace_noop!($($tt)*); $crate::NoopSpan }
180 };
181}
182
183#[cfg(not(feature = "tracing"))]
184pub use __hick_trace_noop_span as trace_span;
185#[cfg(not(feature = "tracing"))]
186pub use __hick_trace_noop_span as debug_span;
187#[cfg(not(feature = "tracing"))]
188pub use __hick_trace_noop_span as info_span;
189
190#[cfg(feature = "stats")]
191pub mod stats {
192 #[cfg(target_has_atomic = "64")]
207 use core::sync::atomic::{AtomicU64, Ordering::Relaxed};
208 #[cfg(not(target_has_atomic = "64"))]
209 use portable_atomic::{AtomicU64, Ordering::Relaxed};
210
211 macro_rules! declare_counters {
212 ($($field:ident => $metric:literal),* $(,)?) => {
213 $(
214 #[inline]
215 pub fn $field(&self, by: u64) {
216 self.$field.fetch_add(by, Relaxed);
217 #[cfg(feature = "metrics")]
218 ::metrics::counter!($metric).increment(by);
219 }
220 )*
221 };
222 }
223
224 macro_rules! declare_gauges {
225 ($(
226 $field:ident => $metric:literal :
227 incr = $incr:ident,
228 decr = $decr:ident,
229 set = $set:ident
230 ),* $(,)?) => {
231 $(
232 #[inline]
233 pub fn $incr(&self, by: u64) {
234 self.$field.fetch_add(by, Relaxed);
235 #[cfg(feature = "metrics")]
236 ::metrics::gauge!($metric).increment(by as f64);
237 }
238
239 #[inline]
240 pub fn $decr(&self, by: u64) {
241 self.$field.fetch_sub(by, Relaxed);
242 #[cfg(feature = "metrics")]
243 ::metrics::gauge!($metric).decrement(by as f64);
244 }
245
246 #[inline]
251 pub fn $set(&self, v: u64) {
252 self.$field.store(v, Relaxed);
253 #[cfg(feature = "metrics")]
254 ::metrics::gauge!($metric).set(v as f64);
255 }
256 )*
257 };
258 }
259
260 #[derive(Default, Debug)]
264 pub struct Stats {
265 packets_rx: AtomicU64,
267 packets_tx: AtomicU64,
268 bytes_rx: AtomicU64,
269 bytes_tx: AtomicU64,
270 packets_dropped: AtomicU64,
271 parse_errors: AtomicU64,
272 send_errors: AtomicU64,
273 questions_rx: AtomicU64,
274 answers_rx: AtomicU64,
275 answers_collected: AtomicU64,
276 answers_suppressed_kas: AtomicU64,
277 duplicate_questions_suppressed: AtomicU64,
278 responses_tx: AtomicU64,
279 probes_tx: AtomicU64,
280 announcements_tx: AtomicU64,
281 goodbyes_tx: AtomicU64,
282 conflicts: AtomicU64,
283 renames: AtomicU64,
284 cache_inserts: AtomicU64,
285 cache_refreshes: AtomicU64,
286 cache_evictions: AtomicU64,
287 cache_expirations: AtomicU64,
288 queries_started: AtomicU64,
289 queries_done: AtomicU64,
290 queries_timeout: AtomicU64,
291 services_registered: AtomicU64,
292 services_established: AtomicU64,
293 cache_size: AtomicU64,
295 queries_active: AtomicU64,
296 services_active: AtomicU64,
297 }
298
299 impl Stats {
300 declare_counters! {
301 packets_rx => "mdns_packets_rx",
302 packets_tx => "mdns_packets_tx",
303 bytes_rx => "mdns_bytes_rx",
304 bytes_tx => "mdns_bytes_tx",
305 packets_dropped => "mdns_packets_dropped",
306 parse_errors => "mdns_parse_errors",
307 send_errors => "mdns_send_errors",
308 questions_rx => "mdns_questions_rx",
309 answers_rx => "mdns_answers_rx",
310 answers_collected => "mdns_answers_collected",
311 answers_suppressed_kas => "mdns_answers_suppressed_kas",
312 duplicate_questions_suppressed => "mdns_duplicate_questions_suppressed",
313 responses_tx => "mdns_responses_tx",
314 probes_tx => "mdns_probes_tx",
315 announcements_tx => "mdns_announcements_tx",
316 goodbyes_tx => "mdns_goodbyes_tx",
317 conflicts => "mdns_conflicts",
318 renames => "mdns_renames",
319 cache_inserts => "mdns_cache_inserts",
320 cache_refreshes => "mdns_cache_refreshes",
321 cache_evictions => "mdns_cache_evictions",
322 cache_expirations => "mdns_cache_expirations",
323 queries_started => "mdns_queries_started",
324 queries_done => "mdns_queries_done",
325 queries_timeout => "mdns_queries_timeout",
326 services_registered => "mdns_services_registered",
327 services_established => "mdns_services_established",
328 }
329
330 declare_gauges! {
331 cache_size => "mdns_cache_size" :
332 incr = incr_cache_size,
333 decr = decr_cache_size,
334 set = set_cache_size,
335 queries_active => "mdns_queries_active" :
336 incr = incr_queries_active,
337 decr = decr_queries_active,
338 set = set_queries_active,
339 services_active => "mdns_services_active" :
340 incr = incr_services_active,
341 decr = decr_services_active,
342 set = set_services_active,
343 }
344
345 pub fn snapshot(&self) -> StatsSnapshot {
351 StatsSnapshot {
352 packets_rx: self.packets_rx.load(Relaxed),
353 packets_tx: self.packets_tx.load(Relaxed),
354 bytes_rx: self.bytes_rx.load(Relaxed),
355 bytes_tx: self.bytes_tx.load(Relaxed),
356 packets_dropped: self.packets_dropped.load(Relaxed),
357 parse_errors: self.parse_errors.load(Relaxed),
358 send_errors: self.send_errors.load(Relaxed),
359 questions_rx: self.questions_rx.load(Relaxed),
360 answers_rx: self.answers_rx.load(Relaxed),
361 answers_collected: self.answers_collected.load(Relaxed),
362 answers_suppressed_kas: self.answers_suppressed_kas.load(Relaxed),
363 duplicate_questions_suppressed: self.duplicate_questions_suppressed.load(Relaxed),
364 responses_tx: self.responses_tx.load(Relaxed),
365 probes_tx: self.probes_tx.load(Relaxed),
366 announcements_tx: self.announcements_tx.load(Relaxed),
367 goodbyes_tx: self.goodbyes_tx.load(Relaxed),
368 conflicts: self.conflicts.load(Relaxed),
369 renames: self.renames.load(Relaxed),
370 cache_inserts: self.cache_inserts.load(Relaxed),
371 cache_refreshes: self.cache_refreshes.load(Relaxed),
372 cache_evictions: self.cache_evictions.load(Relaxed),
373 cache_expirations: self.cache_expirations.load(Relaxed),
374 queries_started: self.queries_started.load(Relaxed),
375 queries_done: self.queries_done.load(Relaxed),
376 queries_timeout: self.queries_timeout.load(Relaxed),
377 services_registered: self.services_registered.load(Relaxed),
378 services_established: self.services_established.load(Relaxed),
379 cache_size: self.cache_size.load(Relaxed),
380 queries_active: self.queries_active.load(Relaxed),
381 services_active: self.services_active.load(Relaxed),
382 }
383 }
384 }
385
386 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
388 pub struct StatsSnapshot {
389 pub packets_rx: u64,
391 pub packets_tx: u64,
392 pub bytes_rx: u64,
393 pub bytes_tx: u64,
394 pub packets_dropped: u64,
395 pub parse_errors: u64,
396 pub send_errors: u64,
397 pub questions_rx: u64,
398 pub answers_rx: u64,
399 pub answers_collected: u64,
400 pub answers_suppressed_kas: u64,
401 pub duplicate_questions_suppressed: u64,
402 pub responses_tx: u64,
403 pub probes_tx: u64,
404 pub announcements_tx: u64,
405 pub goodbyes_tx: u64,
406 pub conflicts: u64,
407 pub renames: u64,
408 pub cache_inserts: u64,
409 pub cache_refreshes: u64,
410 pub cache_evictions: u64,
411 pub cache_expirations: u64,
412 pub queries_started: u64,
413 pub queries_done: u64,
414 pub queries_timeout: u64,
415 pub services_registered: u64,
416 pub services_established: u64,
417 pub cache_size: u64,
419 pub queries_active: u64,
420 pub services_active: u64,
421 }
422}
423
424#[cfg(test)]
425mod tests;