Skip to content

Commit 2466a96

Browse files
committed
Merge branch 'Tunglies-main'
2 parents 02805ad + 61a4d65 commit 2466a96

File tree

6 files changed

+101
-9
lines changed

6 files changed

+101
-9
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this
66
project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.31.3] - 2025-09-22
9+
10+
Add variant `Cleanup::KeepForDays(usize)` to have log files being deleted after a given number of days.
11+
Kudos goes to [Tunglies](https://github.com/Tunglies).
12+
813
## [0.31.2] - 2025-06-27
914

1015
Add syslog-call based `SyslogWriter` connection

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "flexi_logger"
3-
version = "0.31.2"
3+
version = "0.31.3"
44
authors = ["emabee <[email protected]>"]
55
categories = ["development-tools::debugging"]
66
description = """
@@ -69,6 +69,7 @@ nix = { version = "0.30.1", optional = true, features = ["hostname", "syslog"] }
6969
[dev-dependencies]
7070
cond_sync = "0.2"
7171
either = "1.9"
72+
filetime = "0.2.26"
7273
flate2 = "1.0"
7374
glob = "0.3"
7475
serde_derive = "1.0"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ Adds the ability to filter logs by text, but also adds a dependency on the regex
183183

184184
### **`trc`**
185185

186-
An experimental feature that allows using `flexi_logger` functionality with `tracing`.
186+
Allows using `flexi_logger` functionality with `tracing`.
187187

188188
## Versions
189189

src/parameters/cleanup.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,15 @@ pub enum Cleanup {
1717
Never,
1818

1919
/// The specified number of rotated log files are kept.
20-
/// Older files are deleted, if necessary.
20+
/// Older files are deleted.
2121
KeepLogFiles(usize),
2222

23+
/// Log files are kept for the specified number of days.
24+
/// Older files are deleted.
25+
KeepForDays(usize),
26+
2327
/// The specified number of rotated log files are compressed and kept.
24-
/// Older files are deleted, if necessary.
28+
/// Older files are deleted.
2529
#[cfg_attr(docsrs, doc(cfg(feature = "compress")))]
2630
#[cfg(feature = "compress")]
2731
KeepCompressedFiles(usize),

src/writers/file_log_writer/state/list_and_cleanup.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,19 @@ pub(crate) fn remove_or_compress_too_old_logfiles_impl(
9090
infix_filter: &InfixFilter,
9191
writes_direct: bool,
9292
) -> Result<(), std::io::Error> {
93-
let (mut log_limit, compress_limit) = match *cleanup_config {
93+
let (mut log_limit, day_limit, compress_limit): (usize, usize, usize) = match *cleanup_config {
9494
Cleanup::Never => {
9595
return Ok(());
9696
}
97-
Cleanup::KeepLogFiles(log_limit) => (log_limit, 0),
97+
Cleanup::KeepLogFiles(log_limit) => (log_limit, 0, 0),
9898

99-
#[cfg(feature = "compress")]
100-
Cleanup::KeepCompressedFiles(compress_limit) => (0, compress_limit),
99+
Cleanup::KeepForDays(day_limit) => (0, day_limit, 0),
101100

101+
#[cfg(feature = "compress")]
102+
Cleanup::KeepCompressedFiles(compress_limit) => (0, 0, compress_limit),
102103
#[cfg(feature = "compress")]
103104
Cleanup::KeepLogAndCompressedFiles(log_limit, compress_limit) => {
104-
(log_limit, compress_limit)
105+
(log_limit, 0, compress_limit)
105106
}
106107
};
107108

@@ -146,6 +147,20 @@ pub(crate) fn remove_or_compress_too_old_logfiles_impl(
146147
}
147148
}
148149
}
150+
} else if day_limit > 0 {
151+
// Remove files older than the configured day limit
152+
let mod_limit = std::time::SystemTime::now()
153+
.checked_sub(std::time::Duration::from_secs(
154+
u64::try_from(day_limit)
155+
.ok()
156+
.and_then(|days| days.checked_mul(24 * 3600))
157+
.unwrap_or(u64::MAX),
158+
))
159+
.unwrap_or(std::time::UNIX_EPOCH);
160+
161+
if std::fs::metadata(&file)?.modified()? < mod_limit {
162+
std::fs::remove_file(&file)?;
163+
}
149164
}
150165
}
151166

tests/test_cleanup_by_day_limit.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
mod test_utils;
2+
3+
#[test]
4+
fn test_cleanup_by_day_limit() {
5+
use filetime::{set_file_mtime, FileTime};
6+
use flexi_logger::{Cleanup, Criterion, Duplicate, FileSpec, Logger, Naming};
7+
use log::*;
8+
use std::{fs, thread, time::Duration};
9+
10+
let directory = test_utils::dir();
11+
12+
Logger::try_with_str("info")
13+
.unwrap()
14+
.log_to_file(FileSpec::default().directory(&directory))
15+
.duplicate_to_stderr(Duplicate::Info)
16+
.rotate(
17+
Criterion::Size(100),
18+
Naming::Numbers,
19+
Cleanup::KeepForDays(1),
20+
)
21+
.start()
22+
.unwrap();
23+
24+
for i in 0..5 {
25+
info!("log line {i}");
26+
}
27+
28+
let mut log_files: Vec<_> = fs::read_dir(&directory)
29+
.unwrap()
30+
.filter_map(|e| {
31+
let p = e.unwrap().path();
32+
if p.extension().map(|ext| ext == "log").unwrap_or(false) {
33+
Some(p)
34+
} else {
35+
None
36+
}
37+
})
38+
.collect();
39+
let two_days_ago = std::time::SystemTime::now() - Duration::from_secs(2 * 24 * 3600);
40+
let ft = FileTime::from_system_time(two_days_ago);
41+
for file in &log_files {
42+
if file.exists() {
43+
let _ = set_file_mtime(file, ft);
44+
}
45+
}
46+
log_files.sort();
47+
let old_file = log_files.first().expect("should have log files");
48+
let two_days_ago = std::time::SystemTime::now() - Duration::from_secs(2 * 24 * 3600);
49+
let ft = FileTime::from_system_time(two_days_ago);
50+
if old_file.exists() {
51+
set_file_mtime(old_file, ft).unwrap();
52+
}
53+
54+
for i in 0..3 {
55+
info!("trigger cleanup {i}");
56+
thread::sleep(Duration::from_millis(120));
57+
}
58+
59+
let start = std::time::Instant::now();
60+
while old_file.exists() && start.elapsed().as_secs() < 2 {
61+
thread::sleep(Duration::from_millis(50));
62+
}
63+
assert!(
64+
!old_file.exists(),
65+
"old file should be deleted by day_limit cleanup"
66+
);
67+
}

0 commit comments

Comments
 (0)