Skip to content

Commit ecb7e4f

Browse files
committed
appender: impl MakeWriter for RollingFileAppender (#1760)
## 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 <[email protected]>
1 parent c2e2737 commit ecb7e4f

File tree

6 files changed

+286
-126
lines changed

6 files changed

+286
-126
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//! This example demonstrates the use of multiple files with
2+
//! `tracing-appender`'s `RollingFileAppender`
3+
//!
4+
use tracing_appender::rolling;
5+
use tracing_subscriber::fmt::writer::MakeWriterExt;
6+
7+
#[path = "fmt/yak_shave.rs"]
8+
mod yak_shave;
9+
10+
fn main() {
11+
// Log all `tracing` events to files prefixed with `debug`. Since these
12+
// files will be written to very frequently, roll the log file every minute.
13+
let debug_file = rolling::minutely("./logs", "debug");
14+
// Log warnings and errors to a separate file. Since we expect these events
15+
// to occur less frequently, roll that file on a daily basis instead.
16+
let warn_file = rolling::daily("./logs", "warnings").with_max_level(tracing::Level::WARN);
17+
let all_files = debug_file.and(warn_file);
18+
19+
tracing_subscriber::fmt()
20+
.with_writer(all_files)
21+
.with_ansi(false)
22+
.with_max_level(tracing::Level::TRACE)
23+
.init();
24+
25+
yak_shave::shave_all(6);
26+
tracing::info!("sleeping for a minute...");
27+
28+
std::thread::sleep(std::time::Duration::from_secs(60));
29+
30+
tracing::info!("okay, time to shave some more yaks!");
31+
yak_shave::shave_all(10);
32+
}

tracing-appender/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ rust-version = "1.51.0"
2323
[dependencies]
2424
crossbeam-channel = "0.5.0"
2525
time = { version = "0.3", default-features = false, features = ["formatting"] }
26+
parking_lot = { optional = true, version = "0.11.2" }
2627

2728
[dependencies.tracing-subscriber]
2829
path = "../tracing-subscriber"

tracing-appender/src/inner.rs

Lines changed: 0 additions & 105 deletions
This file was deleted.

tracing-appender/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,14 @@ use crate::non_blocking::{NonBlocking, WorkerGuard};
154154

155155
use std::io::Write;
156156

157-
mod inner;
158-
159157
pub mod non_blocking;
160158

161159
pub mod rolling;
162160

163161
mod worker;
164162

163+
pub(crate) mod sync;
164+
165165
/// Convenience function for creating a non-blocking, off-thread writer.
166166
///
167167
/// See the [`non_blocking` module's docs][non_blocking]'s for more details.

0 commit comments

Comments
 (0)