Skip to content

Commit 6fada4c

Browse files
authored
refactor!: logger builder (#124)
Signed-off-by: tison <[email protected]>
1 parent 42ce584 commit 6fada4c

File tree

14 files changed

+81
-35
lines changed

14 files changed

+81
-35
lines changed

.github/workflows/ci.yml

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ jobs:
7979
run: |
8080
set -x
8181
cargo run --example simple_stdout
82+
cargo run --example log_with_logger
8283
cargo run --example multiple_dispatches
8384
cargo run --example custom_layout_filter
8485
cargo run --no-default-features --example simple_stdout

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ All notable changes to this project will be documented in this file.
1010
* `Append::flush` is now fallible.
1111
* `Diagnostic`'s and `Visitor`'s `visit` methods are fallible.
1212
* `NonBlocking` related types and the feature flag are now private.
13+
* `logforth::Builder` is renamed to `logforth::LoggerBuilder`.
14+
* `LoggerBuilder` has no longer an option to configure the global `max_level`. Check its documentation for more details.
1315
* Constructing `RollingFile` and `Syslog` appender is heavily simplified.
1416

1517
Before:
@@ -75,6 +77,7 @@ fn construct_syslog() {
7577

7678
* Add `LogfmtLayout` to support logfmt format.
7779
* Add `GoogleStructuredLogLayout` to support Google structured log format.
80+
* `LoggerBuilder` now has a `build` method to construct the `Logger` for use.
7881

7982
## [0.23.1] 2025-03-23
8083

Cargo.lock

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+6-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ internal-serde = ["dep:serde", "log/kv_serde", "jiff/serde"]
5656
anyhow = { version = "1.0" }
5757
env_filter = { version = "0.1.1" }
5858
jiff = { version = "0.2" }
59-
log = { version = "0.4", features = ["std", "kv"] }
59+
log = { version = "0.4.27", features = ["std", "kv"] }
6060

6161
# Optional dependencies
6262
colored = { version = "3.0", optional = true }
@@ -91,6 +91,11 @@ doc-scrape-examples = true
9191
name = "simple_stdout"
9292
path = "examples/simple_stdout.rs"
9393

94+
[[example]]
95+
doc-scrape-examples = true
96+
name = "log_with_logger"
97+
path = "examples/log_with_logger.rs"
98+
9499
[[example]]
95100
doc-scrape-examples = true
96101
name = "json_stdout"

examples/log_with_logger.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2024 FastLabs Developers
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
use log::LevelFilter;
16+
17+
fn main() {
18+
log::set_max_level(LevelFilter::Trace);
19+
let l = logforth::stdout().build();
20+
21+
log::error!(logger: l, "Hello error!");
22+
log::warn!(logger: l, "Hello warn!");
23+
log::info!(logger: l, "Hello info!");
24+
log::debug!(logger: l, "Hello debug!");
25+
log::trace!(logger: l, "Hello trace!");
26+
}

src/append/journald/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
# Rolling File Appender
1+
# Journald Appender
22

33
This appender is a remix of [tracing-journald](https://crates.io/crates/tracing-journald) and [systemd-journal-logger](https://crates.io/crates/systemd-journal-logger), with several modifications to fit this crate's needs.

src/append/rolling_file/rotation.rs

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub enum Rotation {
3232
}
3333

3434
impl Rotation {
35+
/// Get the next date timestamp based on the current date and rotation policy.
3536
pub fn next_date_timestamp(&self, current_date: &Zoned) -> Option<usize> {
3637
let timestamp_round = ZonedRound::new().mode(RoundMode::Trunc);
3738

@@ -50,6 +51,7 @@ impl Rotation {
5051
Some(next_date.timestamp().as_millisecond() as usize)
5152
}
5253

54+
/// Get the date format string for the rotation policy.
5355
pub fn date_format(&self) -> &'static str {
5456
match *self {
5557
Rotation::Minutely => "%F-%H-%M",

src/diagnostic/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub trait Visitor {
3636

3737
/// A trait representing a Mapped Diagnostic Context (MDC) that provides diagnostic key-values.
3838
pub trait Diagnostic: fmt::Debug + Send + Sync + 'static {
39+
/// Visits the MDC key-values with the provided visitor.
3940
fn visit(&self, visitor: &mut dyn Visitor) -> anyhow::Result<()>;
4041
}
4142

src/diagnostic/static_global.rs

+3
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ pub struct StaticDiagnostic {
3434
}
3535

3636
impl StaticDiagnostic {
37+
/// Creates a new [`StaticDiagnostic`] instance with a prebuilt key-value store.
3738
pub fn new(kvs: BTreeMap<String, String>) -> Self {
3839
Self { kvs }
3940
}
4041

42+
/// Inserts a key-value pair into the static diagnostic .
4143
pub fn insert<K, V>(&mut self, key: K, value: V)
4244
where
4345
K: Into<String>,
@@ -46,6 +48,7 @@ impl StaticDiagnostic {
4648
self.kvs.insert(key.into(), value.into());
4749
}
4850

51+
/// Remove a key-value pair from the static diagnostic.
4952
pub fn remove(&mut self, key: &str) {
5053
self.kvs.remove(key);
5154
}

src/diagnostic/thread_local.rs

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ thread_local! {
3636
pub struct ThreadLocalDiagnostic {}
3737

3838
impl ThreadLocalDiagnostic {
39+
/// Inserts a key-value pair into the thread local diagnostic .
3940
pub fn insert<K, V>(key: K, value: V)
4041
where
4142
K: Into<String>,
@@ -46,6 +47,7 @@ impl ThreadLocalDiagnostic {
4647
});
4748
}
4849

50+
/// Removes a key-value pair from the thread local diagnostic.
4951
pub fn remove(key: &str) {
5052
CONTEXT.with(|map| {
5153
map.borrow_mut().remove(key);

src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
#![deny(missing_docs)]
16+
1517
//! Logforth is a flexible logging framework for Rust applications, providing easy log dispatching
1618
//! and configuration.
1719
//!

src/logger/builder.rs

+29-29
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::Append;
2222
use crate::Diagnostic;
2323
use crate::Filter;
2424

25-
/// Creates a new empty [`Builder`] instance for configuring log dispatching.
25+
/// Creates a new empty [`LoggerBuilder`] instance for configuring log dispatching.
2626
///
2727
/// # Examples
2828
///
@@ -33,11 +33,11 @@ use crate::Filter;
3333
/// .dispatch(|d| d.append(append::Stderr::default()))
3434
/// .apply();
3535
/// ```
36-
pub fn builder() -> Builder {
37-
Builder::new()
36+
pub fn builder() -> LoggerBuilder {
37+
LoggerBuilder::new()
3838
}
3939

40-
/// Creates a [`Builder`] with a default [`append::Stdout`] appender and an [`env_filter`](https://crates.io/crates/env_filter)
40+
/// Creates a [`LoggerBuilder`] with a default [`append::Stdout`] appender and an [`env_filter`](https://crates.io/crates/env_filter)
4141
/// respecting `RUST_LOG`.
4242
///
4343
/// # Examples
@@ -46,14 +46,14 @@ pub fn builder() -> Builder {
4646
/// logforth::stdout().apply();
4747
/// log::error!("This error will be logged to stdout.");
4848
/// ```
49-
pub fn stdout() -> Builder {
49+
pub fn stdout() -> LoggerBuilder {
5050
builder().dispatch(|d| {
5151
d.filter(EnvFilter::from_default_env())
5252
.append(append::Stdout::default())
5353
})
5454
}
5555

56-
/// Creates a [`Builder`] with a default [`append::Stderr`] appender and an [`env_filter`](https://crates.io/crates/env_filter)
56+
/// Creates a [`LoggerBuilder`] with a default [`append::Stderr`] appender and an [`env_filter`](https://crates.io/crates/env_filter)
5757
/// respecting `RUST_LOG`.
5858
///
5959
/// # Examples
@@ -62,7 +62,7 @@ pub fn stdout() -> Builder {
6262
/// logforth::stderr().apply();
6363
/// log::info!("This info will be logged to stderr.");
6464
/// ```
65-
pub fn stderr() -> Builder {
65+
pub fn stderr() -> LoggerBuilder {
6666
builder().dispatch(|d| {
6767
d.filter(EnvFilter::from_default_env())
6868
.append(append::Stderr::default())
@@ -80,25 +80,19 @@ pub fn stderr() -> Builder {
8080
/// .dispatch(|d| d.append(append::Stdout::default()))
8181
/// .apply();
8282
/// ```
83-
#[must_use = "call `apply` to set the global logger"]
83+
#[must_use = "call `apply` to set the global logger or `build` to construct a logger instance"]
8484
#[derive(Debug)]
85-
pub struct Builder {
85+
pub struct LoggerBuilder {
8686
// stashed dispatches
8787
dispatches: Vec<Dispatch>,
88-
89-
// default to trace - we need this because the global default is OFF
90-
max_level: LevelFilter,
9188
}
9289

93-
impl Builder {
90+
impl LoggerBuilder {
9491
fn new() -> Self {
95-
Builder {
96-
dispatches: vec![],
97-
max_level: LevelFilter::Trace,
98-
}
92+
LoggerBuilder { dispatches: vec![] }
9993
}
10094

101-
/// Registers a new dispatch with the [`Builder`].
95+
/// Registers a new dispatch with the [`LoggerBuilder`].
10296
///
10397
/// # Examples
10498
///
@@ -117,27 +111,28 @@ impl Builder {
117111
self
118112
}
119113

120-
/// Sets the global maximum log level. Default to [`LevelFilter::Trace`].
121-
///
122-
/// This will be passed to `log::set_max_level()`.
114+
/// Build the [`Logger`].
123115
///
124116
/// # Examples
125117
///
126118
/// ```
127-
/// logforth::builder()
128-
/// .max_level(log::LevelFilter::Warn)
129-
/// .apply();
119+
/// let l = logforth::builder().build();
120+
/// log::error!(logger: l, "Hello error!");
130121
/// ```
131-
pub fn max_level(mut self, max_level: LevelFilter) -> Self {
132-
self.max_level = max_level;
133-
self
122+
pub fn build(self) -> Logger {
123+
Logger::new(self.dispatches)
134124
}
135125

136126
/// Sets up the global logger with all the configured dispatches.
137127
///
138128
/// This should be called early in the execution of a Rust program. Any log events that occur
139129
/// before initialization will be ignored.
140130
///
131+
/// This will set the global maximum log level to [`LevelFilter::Trace`]. To override this,
132+
/// call [`log::set_max_level`] after this function. Alternatively, you can obtain a [`Logger`]
133+
/// instance by calling [`LoggerBuilder::build`], and then call [`log::set_boxed_logger`]
134+
/// manually.
135+
///
141136
/// # Errors
142137
///
143138
/// Returns an error if a global logger has already been set.
@@ -151,9 +146,9 @@ impl Builder {
151146
/// }
152147
/// ```
153148
pub fn try_apply(self) -> Result<(), log::SetLoggerError> {
154-
let logger = Logger::new(self.dispatches);
149+
let logger = self.build();
155150
log::set_boxed_logger(Box::new(logger))?;
156-
log::set_max_level(self.max_level);
151+
log::set_max_level(LevelFilter::Trace);
157152
Ok(())
158153
}
159154

@@ -162,6 +157,11 @@ impl Builder {
162157
/// This function will panic if it is called more than once, or if another library has already
163158
/// initialized a global logger.
164159
///
160+
/// This function will set the global maximum log level to [`LevelFilter::Trace`]. To override
161+
/// this, call [`log::set_max_level`] after this function. Alternatively, you can obtain a
162+
/// [`Logger`] instance by calling [`LoggerBuilder::build`], and then call
163+
/// [`log::set_boxed_logger`] manually.
164+
///
165165
/// # Panics
166166
///
167167
/// Panics if the global logger has already been set.

src/logger/log_impl.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ use crate::Append;
2222
use crate::Diagnostic;
2323
use crate::Filter;
2424

25-
/// A logger facade that dispatches log records to one or more [`Dispatch`] instances.
25+
/// A logger facade that dispatches log records to one or more dispatcher.
2626
///
2727
/// This struct implements [`log::Log`] to bridge Logforth's logging implementations
2828
/// with the [`log`] crate.
2929
#[derive(Debug)]
30-
pub(super) struct Logger {
30+
pub struct Logger {
3131
dispatches: Vec<Dispatch>,
3232
}
3333

src/logger/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ mod builder;
1616
pub use builder::*;
1717

1818
mod log_impl;
19+
pub use log_impl::Logger;

0 commit comments

Comments
 (0)