Skip to content

Commit

Permalink
Add a weekly log rotation interval
Browse files Browse the repository at this point in the history
  • Loading branch information
NickCaplinger committed Feb 14, 2025
1 parent 813aee5 commit 9c6c2fb
Showing 1 changed file with 56 additions and 4 deletions.
60 changes: 56 additions & 4 deletions tracing-appender/src/rolling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ enum RotationKind {
Minutely,
Hourly,
Daily,
Weekly,
Never,
}

Expand All @@ -454,6 +455,8 @@ impl Rotation {
pub const HOURLY: Self = Self(RotationKind::Hourly);
/// Provides a daily rotation
pub const DAILY: Self = Self(RotationKind::Daily);
/// Provides a weekly rotation
pub const WEEKLY: Self = Self(RotationKind::Weekly);
/// Provides a rotation that never rotates.
pub const NEVER: Self = Self(RotationKind::Never);

Expand All @@ -462,13 +465,14 @@ impl Rotation {
Rotation::MINUTELY => *current_date + Duration::minutes(1),
Rotation::HOURLY => *current_date + Duration::hours(1),
Rotation::DAILY => *current_date + Duration::days(1),
Rotation::WEEKLY => *current_date + Duration::weeks(1),
Rotation::NEVER => return None,
};
Some(self.round_date(&unrounded_next_date))
Some(self.round_date(unrounded_next_date))
}

// note that this method will panic if passed a `Rotation::NEVER`.
pub(crate) fn round_date(&self, date: &OffsetDateTime) -> OffsetDateTime {
pub(crate) fn round_date(&self, date: OffsetDateTime) -> OffsetDateTime {
match *self {
Rotation::MINUTELY => {
let time = Time::from_hms(date.hour(), date.minute(), 0)
Expand All @@ -485,6 +489,18 @@ impl Rotation {
.expect("Invalid time; this is a bug in tracing-appender");
date.replace_time(time)
}
Rotation::WEEKLY => {
let time = Time::from_hms(0, 0, 0)
.expect("Invalid time; this is a bug in tracing-appender");
let date = date.replace_time(time);
let rounded_ordinal = Rotation::round_ordinal_to_week(date.date());

date.replace_date(
Date::from_ordinal_date(date.year(), rounded_ordinal).expect(
"ordinal should never be out of range; this is a bug in tracing-appender",
),
)
}
// Rotation::NEVER is impossible to round.
Rotation::NEVER => {
unreachable!("Rotation::NEVER is impossible to round.")
Expand All @@ -497,10 +513,20 @@ impl Rotation {
Rotation::MINUTELY => format_description::parse("[year]-[month]-[day]-[hour]-[minute]"),
Rotation::HOURLY => format_description::parse("[year]-[month]-[day]-[hour]"),
Rotation::DAILY => format_description::parse("[year]-[month]-[day]"),
Rotation::WEEKLY => format_description::parse("[year]-[month]-[day]"),
Rotation::NEVER => format_description::parse("[year]-[month]-[day]"),
}
.expect("Unable to create a formatter; this is a bug in tracing-appender")
}

fn round_ordinal_to_week(date: Date) -> u16 {
let ordinal = date.ordinal() as u16;

Check failure on line 523 in tracing-appender/src/rolling.rs

View workflow job for this annotation

GitHub Actions / clippy

casting to the same type is unnecessary (`u16` -> `u16`)

error: casting to the same type is unnecessary (`u16` -> `u16`) --> tracing-appender/src/rolling.rs:523:23 | 523 | let ordinal = date.ordinal() as u16; | ^^^^^^^^^^^^^^^^^^^^^ help: try: `date.ordinal()` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast = note: `-D clippy::unnecessary-cast` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_cast)]`
if ordinal <= 7 {
1
} else {
ordinal - (ordinal % 7)
}
}
}

// === impl RollingWriter ===
Expand Down Expand Up @@ -761,6 +787,11 @@ mod test {
test_appender(Rotation::DAILY, "daily.log");
}

#[test]
fn write_weekly_log() {
test_appender(Rotation::WEEKLY, "weekly.log");
}

#[test]
fn write_never_log() {
test_appender(Rotation::NEVER, "never.log");
Expand All @@ -778,11 +809,17 @@ mod test {
let next = Rotation::HOURLY.next_date(&now).unwrap();
assert_eq!((now + Duration::HOUR).hour(), next.hour());

// daily-basis
// per-day basis
let now = OffsetDateTime::now_utc();
let next = Rotation::DAILY.next_date(&now).unwrap();
assert_eq!((now + Duration::DAY).day(), next.day());

// per-week basis
let now = OffsetDateTime::now_utc();
let now_rounded = Rotation::WEEKLY.round_date(now);
let next = Rotation::WEEKLY.next_date(&now).unwrap();
assert!(now_rounded < next);

// never
let now = OffsetDateTime::now_utc();
let next = Rotation::NEVER.next_date(&now);
Expand All @@ -795,7 +832,22 @@ mod test {
)]
fn test_never_date_rounding() {
let now = OffsetDateTime::now_utc();
let _ = Rotation::NEVER.round_date(&now);
let _ = Rotation::NEVER.round_date(now);
}

#[test]
fn test_ordinal_rounding() {
let date = Date::from_ordinal_date(2025, 1).unwrap();
assert_eq!(Rotation::round_ordinal_to_week(date), 1);

let date = Date::from_ordinal_date(2025, 2).unwrap();
assert_eq!(Rotation::round_ordinal_to_week(date), 1);

let date = Date::from_ordinal_date(2025, 7).unwrap();
assert_eq!(Rotation::round_ordinal_to_week(date), 1);

let date = Date::from_ordinal_date(2025, 8).unwrap();
assert_eq!(Rotation::round_ordinal_to_week(date), 7);
}

#[test]
Expand Down

0 comments on commit 9c6c2fb

Please sign in to comment.