Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ jobs:
cargo run --no-default-features --example simple_stdout
cargo run --features="layout-json" --example json_stdout
cargo run --features="layout-json,append-rolling-file" --example rolling_file
cargo run --features="layout-json,append-single-file" --example single_file
cargo run --features="layout-json,append-rolling-file" --example single_file
cargo run --features="fastrace/enable,diagnostic-fastrace,layout-google-cloud-logging" --example google_cloud_logging
cargo run --features="fastrace/enable,append-fastrace,diagnostic-fastrace" --example fastrace

Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,23 @@ All notable changes to this project will be documented in this file.
### Breaking changes

* `JsonLayout` now collects diagnostics context into a separate field `diags`.
* `SingleFile` appender is removed. You can replace it with `RollingFile` with `Rotation::Never`.
* `RollingFile` appender now requires `filename` when constructing.
* `RollingFile`'s `filename_prefix` is now renamed to mandatory `filename`.
* `RollingFile`'s `max_log_files` and `max_file_size` now take `NonZeroUsize`.
* RollingFile's rollover strategy has been changed:
```
from:
app.log
app.1.log
app.2.log

to:
app.log
app.1.log - old app.log
app.2.log - old app.1.log
- old app.2.log deleted
```

## [0.27.0] 2025-08-18

Expand Down
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ append-opentelemetry = [
"dep:opentelemetry_sdk",
]
append-rolling-file = ["internal-non-blocking"]
append-single-file = ["internal-non-blocking"]
append-syslog = ["internal-non-blocking", "dep:fasyslog"]

# Layouts
Expand Down Expand Up @@ -130,7 +129,7 @@ required-features = ["append-rolling-file", "layout-json"]
doc-scrape-examples = true
name = "single_file"
path = "examples/single_file.rs"
required-features = ["append-single-file", "layout-json"]
required-features = ["append-rolling-file", "layout-json"]

[[example]]
doc-scrape-examples = true
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ Other appenders, filters, layouts, and diagnostics are still evolving and may ch

The following components yet to be unstabilized have known production usage and are considered reliable:

* Appenders: `Fastrace`, `OpentelemetryLog`, `SingleFile`, and `RollingFile`
* Appenders: `Fastrace`, `OpentelemetryLog`, and `RollingFile`
* Layouts: `LogfmtLayout` and `GoogleCloudLoggingLayout`
* Diagnostics: `FastraceDiagnostic`

Expand All @@ -122,7 +122,7 @@ The rest components, due to their external dependencies and several missing feat

**What are the missing features?**

Before stabilize `SingleFile`, `RollingFile` and `Syslog` appenders that depend on the `NonBlocking` utility, I need to decide whether an `AsyncAppend` composition is better (see [#145](https://github.com/fast/logforth/issues/145)).
Before stabilize `RollingFile` and `Syslog` appenders that depend on the `NonBlocking` utility, I need to decide whether an `AsyncAppend` composition is better (see [#145](https://github.com/fast/logforth/issues/145)).

Otherwise, how to share utilities like `NonBlocking` and `LevelColor` between different separate crates without duplicating code is still an open question.

Expand Down
3 changes: 1 addition & 2 deletions examples/rolling_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ use logforth::append::rolling_file::Rotation;
use logforth::layout::JsonLayout;

fn main() {
let (rolling_writer, _guard) = RollingFileBuilder::new("logs")
let (rolling_writer, _guard) = RollingFileBuilder::new("logs", "my_app")
.layout(JsonLayout::default())
.rotation(Rotation::Daily)
.filename_prefix("app_log")
.build()
.unwrap();

Expand Down
19 changes: 11 additions & 8 deletions examples/single_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,30 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use logforth::append::single_file::SingleFileBuilder;
use logforth::append::rolling_file::RollingFileBuilder;
use logforth::append::rolling_file::Rotation;
use logforth::layout::JsonLayout;

fn main() {
let (single_writer, _guard) = SingleFileBuilder::new("my.log")
let (rolling_writer, _guard) = RollingFileBuilder::new("logs", "my_app")
.filename_suffix("log")
.layout(JsonLayout::default())
.rotation(Rotation::Never)
.build()
.unwrap();

logforth::builder()
.dispatch(|d| d.filter(log::LevelFilter::Trace).append(single_writer))
.dispatch(|d| d.filter(log::LevelFilter::Trace).append(rolling_writer))
.apply();

let repeat = 1;

for i in 0..repeat {
log::error!("Hello error!");
log::warn!("Hello warn!");
log::info!("Hello info!");
log::debug!("Hello debug!");
log::trace!("Hello trace!");
log::error!("Hello single error!");
log::warn!("Hello single warn!");
log::info!("Hello single info!");
log::debug!("Hello single debug!");
log::trace!("Hello single trace!");

if i + 1 < repeat {
std::thread::sleep(std::time::Duration::from_secs(10));
Expand Down
4 changes: 0 additions & 4 deletions src/append/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ mod journald;
pub mod opentelemetry;
#[cfg(feature = "append-rolling-file")]
pub mod rolling_file;
#[cfg(feature = "append-single-file")]
pub mod single_file;
mod stdio;
#[cfg(feature = "append-syslog")]
pub mod syslog;
Expand All @@ -41,8 +39,6 @@ pub use self::journald::Journald;
pub use self::opentelemetry::OpentelemetryLog;
#[cfg(feature = "append-rolling-file")]
pub use self::rolling_file::RollingFile;
#[cfg(feature = "append-single-file")]
pub use self::single_file::SingleFile;
pub use self::stdio::Stderr;
pub use self::stdio::Stdout;
#[cfg(feature = "append-syslog")]
Expand Down
25 changes: 13 additions & 12 deletions src/append/rolling_file/append.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::num::NonZeroUsize;
use std::path::PathBuf;
use std::time::Duration;

Expand Down Expand Up @@ -42,9 +43,13 @@ pub struct RollingFileBuilder {

impl RollingFileBuilder {
/// Create a new builder.
pub fn new(basedir: impl Into<PathBuf>) -> Self {
///
/// # Error
///
/// If `filename` is empty, [`RollingFileBuilder::build`] would return an error.
pub fn new(basedir: impl Into<PathBuf>, filename: impl Into<String>) -> Self {
Self {
builder: RollingFileWriterBuilder::new(basedir),
builder: RollingFileWriterBuilder::new(basedir, filename),
layout: Box::new(TextLayout::default().no_color()),

thread_name: "logforth-rolling-file".to_string(),
Expand All @@ -57,7 +62,9 @@ impl RollingFileBuilder {
///
/// # Errors
///
/// Returns an error if the log directory cannot be created.
/// Returns an error if:
/// * The log directory cannot be created.
/// * The configured filename is empty.
pub fn build(self) -> anyhow::Result<(RollingFile, DropGuard)> {
let RollingFileBuilder {
builder,
Expand All @@ -84,7 +91,7 @@ impl RollingFileBuilder {
/// use logforth::append::rolling_file::RollingFileBuilder;
/// use logforth::layout::JsonLayout;
///
/// let builder = RollingFileBuilder::new("my_service");
/// let builder = RollingFileBuilder::new("my_service", "my_app");
/// builder.layout(JsonLayout::default());
/// ```
pub fn layout(mut self, layout: impl Into<Box<dyn Layout>>) -> Self {
Expand Down Expand Up @@ -116,26 +123,20 @@ impl RollingFileBuilder {
self
}

/// Sets the filename prefix.
pub fn filename_prefix(mut self, prefix: impl Into<String>) -> Self {
self.builder = self.builder.filename_prefix(prefix);
self
}

/// Sets the filename suffix.
pub fn filename_suffix(mut self, suffix: impl Into<String>) -> Self {
self.builder = self.builder.filename_suffix(suffix);
self
}

/// Sets the maximum number of log files to keep.
pub fn max_log_files(mut self, n: usize) -> Self {
pub fn max_log_files(mut self, n: NonZeroUsize) -> Self {
self.builder = self.builder.max_log_files(n);
self
}

/// Sets the maximum size of a log file in bytes.
pub fn max_file_size(mut self, n: usize) -> Self {
pub fn max_file_size(mut self, n: NonZeroUsize) -> Self {
self.builder = self.builder.max_file_size(n);
self
}
Expand Down
3 changes: 1 addition & 2 deletions src/append/rolling_file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@
//! use logforth::append::rolling_file::Rotation;
//! use logforth::layout::JsonLayout;
//!
//! let (rolling_writer, _guard) = RollingFileBuilder::new("logs")
//! let (rolling_writer, _guard) = RollingFileBuilder::new("logs", "app_log")
//! .layout(JsonLayout::default())
//! .rotation(Rotation::Daily)
//! .filename_prefix("app_log")
//! .build()
//! .unwrap();
//!
Expand Down
Loading