Skip to content

Commit e56ed78

Browse files
committed
feat: add a composable Layer
1 parent 737c9b7 commit e56ed78

File tree

2 files changed

+108
-46
lines changed

2 files changed

+108
-46
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ serde_json = "1.0.122"
1414
time = "0.3.36"
1515
tracing = "0.1.40"
1616
tracing-log = { version = "0.2.0", optional = true, default-features = false }
17+
tracing-subscriber = { version = "0.3.18", optional = true, default-features = false }
1718

1819
[features]
1920
tracing-log = ["dep:tracing-log"]
21+
layer = ["dep:tracing-subscriber"]

src/lib.rs

Lines changed: 106 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -16,51 +16,31 @@ pub fn prepare_database(conn: &Connection) -> rusqlite::Result<()> {
1616
conn.execute(SQL_SCHEMA, ()).map(|_| {})
1717
}
1818

19+
/// A `Layer` to write events to a sqlite database.
20+
/// This type can be composed with other `Subscriber`s and `Layer`s.
1921
#[derive(Debug)]
20-
pub struct Subscriber {
21-
id: AtomicU64,
22+
pub struct Layer {
2223
connection: Mutex<Connection>,
2324
max_level: LevelFilter,
2425
black_list: Option<Box<[&'static str]>>,
2526
white_list: Option<Box<[&'static str]>>,
2627
}
2728

28-
impl Subscriber {
29-
pub fn new(connection: Connection) -> Self {
30-
Self::with_max_level(connection, LevelFilter::TRACE)
31-
}
32-
33-
fn with_details(
34-
connection: Mutex<Connection>,
35-
max_level: LevelFilter,
36-
black_list: Option<Box<[&'static str]>>,
37-
white_list: Option<Box<[&'static str]>>,
38-
) -> Self {
39-
Self {
40-
id: AtomicU64::new(1),
41-
connection,
42-
max_level,
43-
black_list,
44-
white_list,
45-
}
46-
}
47-
48-
pub fn with_max_level(connection: Connection, max_level: LevelFilter) -> Self {
49-
Self::with_details(Mutex::new(connection), max_level, None, None)
50-
}
51-
29+
impl Layer {
5230
pub fn black_list(&self) -> Option<&[&'static str]> {
5331
self.black_list.as_deref()
5432
}
5533

5634
pub fn white_list(&self) -> Option<&[&'static str]> {
5735
self.white_list.as_deref()
5836
}
59-
}
6037

61-
impl tracing::Subscriber for Subscriber {
38+
pub fn max_level(&self) -> &LevelFilter {
39+
&self.max_level
40+
}
41+
6242
fn enabled(&self, metadata: &tracing::Metadata<'_>) -> bool {
63-
metadata.level() <= &self.max_level
43+
metadata.level() <= self.max_level()
6444
&& metadata.module_path().map_or(true, |m| {
6545
let starts_with = |module: &&str| m.starts_with(module);
6646
let has_module = |modules: &[&str]| modules.iter().any(starts_with);
@@ -73,16 +53,7 @@ impl tracing::Subscriber for Subscriber {
7353
Some(self.max_level)
7454
}
7555

76-
fn new_span(&self, _span: &span::Attributes<'_>) -> span::Id {
77-
let id = self.id.fetch_add(1, std::sync::atomic::Ordering::AcqRel);
78-
span::Id::from_u64(id)
79-
}
80-
81-
fn record(&self, _span: &span::Id, _values: &span::Record<'_>) {}
82-
83-
fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}
84-
85-
fn event(&self, event: &tracing::Event<'_>) {
56+
fn on_event(&self, event: &tracing::Event<'_>) {
8657
#[cfg(feature = "tracing-log")]
8758
let normalized_meta = event.normalized_metadata();
8859
#[cfg(feature = "tracing-log")]
@@ -117,6 +88,85 @@ impl tracing::Subscriber for Subscriber {
11788
.unwrap();
11889
}
11990

91+
pub fn to_subscriber(self) -> Subscriber {
92+
Subscriber::with_layer(self)
93+
}
94+
}
95+
96+
#[cfg(feature = "layer")]
97+
impl<S: tracing::Subscriber> tracing_subscriber::Layer<S> for Layer {
98+
fn enabled(
99+
&self,
100+
metadata: &tracing::Metadata<'_>,
101+
_: tracing_subscriber::layer::Context<'_, S>,
102+
) -> bool {
103+
self.enabled(metadata)
104+
}
105+
106+
fn on_event(&self, event: &tracing::Event<'_>, _: tracing_subscriber::layer::Context<'_, S>) {
107+
self.on_event(event)
108+
}
109+
}
110+
111+
/// A simple `Subscriber` that wraps `Layer`[crate::Layer].
112+
#[derive(Debug)]
113+
pub struct Subscriber {
114+
id: AtomicU64,
115+
layer: Layer,
116+
}
117+
118+
impl Subscriber {
119+
pub fn new(connection: Connection) -> Self {
120+
Self::with_max_level(connection, LevelFilter::TRACE)
121+
}
122+
123+
fn with_layer(layer: Layer) -> Self {
124+
Self {
125+
id: AtomicU64::new(1),
126+
layer,
127+
}
128+
}
129+
130+
pub fn with_max_level(connection: Connection, max_level: LevelFilter) -> Self {
131+
Self::with_layer(Layer {
132+
connection: Mutex::new(connection),
133+
max_level,
134+
black_list: None,
135+
white_list: None,
136+
})
137+
}
138+
139+
pub fn black_list(&self) -> Option<&[&'static str]> {
140+
self.layer.black_list()
141+
}
142+
143+
pub fn white_list(&self) -> Option<&[&'static str]> {
144+
self.layer.white_list()
145+
}
146+
}
147+
148+
impl tracing::Subscriber for Subscriber {
149+
fn enabled(&self, metadata: &tracing::Metadata<'_>) -> bool {
150+
self.layer.enabled(metadata)
151+
}
152+
153+
fn max_level_hint(&self) -> Option<tracing::level_filters::LevelFilter> {
154+
self.layer.max_level_hint()
155+
}
156+
157+
fn new_span(&self, _span: &span::Attributes<'_>) -> span::Id {
158+
let id = self.id.fetch_add(1, std::sync::atomic::Ordering::AcqRel);
159+
span::Id::from_u64(id)
160+
}
161+
162+
fn record(&self, _span: &span::Id, _values: &span::Record<'_>) {}
163+
164+
fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}
165+
166+
fn event(&self, event: &tracing::Event<'_>) {
167+
self.layer.on_event(event)
168+
}
169+
120170
fn enter(&self, _span: &span::Id) {}
121171

122172
fn exit(&self, _span: &span::Id) {}
@@ -173,18 +223,28 @@ impl SubscriberBuilder {
173223
}
174224

175225
pub fn build(self, conn: Connection) -> Subscriber {
176-
Subscriber::with_details(
177-
Mutex::new(conn),
178-
self.max_level,
179-
self.black_list,
180-
self.white_list,
181-
)
226+
self.build_layer(conn).to_subscriber()
182227
}
183228

184229
pub fn build_prepared(self, conn: Connection) -> Result<Subscriber, rusqlite::Error> {
185230
prepare_database(&conn)?;
186231

187-
Ok(self.build(conn))
232+
self.build_layer_prepared(conn).map(|l| l.to_subscriber())
233+
}
234+
235+
pub fn build_layer(self, conn: Connection) -> Layer {
236+
Layer {
237+
connection: Mutex::new(conn),
238+
max_level: self.max_level,
239+
black_list: self.black_list,
240+
white_list: self.white_list,
241+
}
242+
}
243+
244+
pub fn build_layer_prepared(self, conn: Connection) -> Result<Layer, rusqlite::Error> {
245+
prepare_database(&conn)?;
246+
247+
Ok(self.build_layer(conn))
188248
}
189249
}
190250

0 commit comments

Comments
 (0)