tuwunel_core/log/capture/mod.rs
1//! Ephemeral tracing-event capture.
2//!
3//! Captures combine optional predicates with callbacks and remain active for a
4//! scope guard's lifetime. Formatting helpers support administrative output.
5
6pub mod data;
7mod guard;
8pub mod layer;
9pub mod state;
10pub mod util;
11
12use std::sync::{Arc, Mutex};
13
14pub use data::Data;
15pub use guard::Guard;
16pub use layer::{Layer, Value};
17pub use state::State;
18pub use util::*;
19
20/// Predicate used to select tracing events for a capture.
21///
22/// Returning true delivers the event to the capture callback. Filters must be
23/// thread safe because tracing events can originate on any thread. They execute
24/// while registration state is read-locked and must not mutate captures on the
25/// same state.
26pub type Filter = dyn Fn(Data<'_>) -> bool + Send + Sync + 'static;
27
28/// Callback invoked for each tracing event selected by a capture.
29///
30/// The callback is serialized by the owning capture so mutable state can be
31/// updated safely. It executes while registration state is read-locked and must
32/// not mutate captures on the same state.
33pub type Closure = dyn FnMut(Data<'_>) + Send + Sync + 'static;
34
35/// Capture instance state.
36pub struct Capture {
37 state: Arc<State>,
38 filter: Option<Box<Filter>>,
39 closure: Mutex<Box<Closure>>,
40}
41
42impl Capture {
43 /// Construct a new capture instance. Capture does not start until the Guard
44 /// is in scope.
45 #[must_use]
46 pub fn new<F, C>(state: &Arc<State>, filter: Option<F>, closure: C) -> Arc<Self>
47 where
48 F: Fn(Data<'_>) -> bool + Send + Sync + 'static,
49 C: FnMut(Data<'_>) + Send + Sync + 'static,
50 {
51 Arc::new(Self {
52 state: state.clone(),
53 filter: filter.map(|p| -> Box<Filter> { Box::new(p) }),
54 closure: Mutex::new(Box::new(closure)),
55 })
56 }
57
58 /// Creates one active registration for the lifetime of a scope guard.
59 ///
60 /// Registration happens before the guard is returned. Multiple guards can
61 /// register the same capture, and dropping each guard removes its own
62 /// registration.
63 #[must_use]
64 pub fn start(self: &Arc<Self>) -> Guard {
65 self.state.add(self);
66 Guard { capture: self.clone() }
67 }
68
69 /// Removes one active registration for this capture.
70 ///
71 /// Calling the method for an inactive capture has no effect. Other
72 /// registrations of the same capture remain active, and a callback already
73 /// in progress can finish before removal becomes observable.
74 pub fn stop(self: &Arc<Self>) { self.state.del(self); }
75}