Skip to main content

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}