Skip to content

Commit

Permalink
appender: impl MakeWriter for RollingFileAppender (#1760)
Browse files Browse the repository at this point in the history
## Motivation

Currently, `tracing-appender`'s `RollingFileAppender` does not implement
the `MakeWriter` trait. This means it can only be used by either
wrapping it in `NonBlocking`, or by wrapping it in a `Mutex`. However,
this shouldn't be strictly necessary, as `&File` implements `io::Write`.
It should thus only be necessary to introduce locking when we are in the
process of _rotating_ the log file.

## Solution

This branch adds a `MakeWriter` implementation for
`RollingFileAppender`. This is done by moving the file itself inside of
an `RwLock`, so that a read lock is acquired to write to the file. This
allows multiple threads to write to the file without contention. When
the file needs to be rolled, the rolling thread acquires the write lock
to replace the file. Acquiring the write lock is guarded by an atomic
CAS on the timestamp, so that only a single thread will try to roll the
file. This prevents other threads from immediately rolling the file
_again_ when the write lock is released.

I...should probably write tests for that, though.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
  • Loading branch information
hawkw committed Dec 19, 2021
1 parent 89de8f7 commit 0b8e9a6
Show file tree
Hide file tree
Showing 6 changed files with 286 additions and 126 deletions.
32 changes: 32 additions & 0 deletions examples/examples/appender-multifile.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//! This example demonstrates the use of multiple files with
//! `tracing-appender`'s `RollingFileAppender`
//!
use tracing_appender::rolling;
use tracing_subscriber::fmt::writer::MakeWriterExt;

#[path = "fmt/yak_shave.rs"]
mod yak_shave;

fn main() {
// Log all `tracing` events to files prefixed with `debug`. Since these
// files will be written to very frequently, roll the log file every minute.
let debug_file = rolling::minutely("./logs", "debug");
// Log warnings and errors to a separate file. Since we expect these events
// to occur less frequently, roll that file on a daily basis instead.
let warn_file = rolling::daily("./logs", "warnings").with_max_level(tracing::Level::WARN);
let all_files = debug_file.and(warn_file);

tracing_subscriber::fmt()
.with_writer(all_files)
.with_ansi(false)
.with_max_level(tracing::Level::TRACE)
.init();

yak_shave::shave_all(6);
tracing::info!("sleeping for a minute...");

std::thread::sleep(std::time::Duration::from_secs(60));

tracing::info!("okay, time to shave some more yaks!");
yak_shave::shave_all(10);
}
1 change: 1 addition & 0 deletions tracing-appender/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ rust-version = "1.51.0"
[dependencies]
crossbeam-channel = "0.5.0"
time = { version = "0.3", default-features = false, features = ["formatting"] }
parking_lot = { optional = true, version = "0.11.2" }

[dependencies.tracing-subscriber]
path = "../tracing-subscriber"
Expand Down
105 changes: 0 additions & 105 deletions tracing-appender/src/inner.rs

This file was deleted.

4 changes: 2 additions & 2 deletions tracing-appender/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,14 @@ use crate::non_blocking::{NonBlocking, WorkerGuard};

use std::io::Write;

mod inner;

pub mod non_blocking;

pub mod rolling;

mod worker;

pub(crate) mod sync;

/// Convenience function for creating a non-blocking, off-thread writer.
///
/// See the [`non_blocking` module's docs][non_blocking]'s for more details.
Expand Down
Loading

0 comments on commit 0b8e9a6

Please sign in to comment.