Skip to content

Commit

Permalink
refactor: move Rotation into one separate module and add test for it
Browse files Browse the repository at this point in the history
  • Loading branch information
1996fanrui committed Aug 11, 2024
1 parent d2db4c7 commit 48ab6df
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 60 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ serde_json = { version = "1.0", optional = true }
time = { version = "0.3", features = [
"formatting",
"parsing",
"macros",
], optional = true }

## Fastrace dependencies
Expand Down
3 changes: 2 additions & 1 deletion src/append/rolling_file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ pub use non_blocking::NonBlockingBuilder;
pub use non_blocking::WorkerGuard;
pub use rolling::RollingFileWriter;
pub use rolling::RollingFileWriterBuilder;
pub use rolling::Rotation;
pub use rotation::Rotation;

mod append;
mod non_blocking;
mod rolling;
mod rotation;
mod worker;

#[derive(Debug)]
Expand Down
60 changes: 1 addition & 59 deletions src/append/rolling_file/rolling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,12 @@ use std::io::Write;
use std::path::Path;
use std::path::PathBuf;

use crate::append::rolling_file::Rotation;
use anyhow::Context;
use parking_lot::RwLock;
use time::format_description;
use time::Date;
use time::Duration;
use time::OffsetDateTime;
use time::Time;

/// A file writer with the ability to rotate log files at a fixed schedule.
#[derive(Debug)]
Expand Down Expand Up @@ -338,60 +337,3 @@ impl State {
self.next_date_timestamp = self.rotation.next_date_timestamp(&now);
}
}

/// Defines a fixed period for rolling of a log file.
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum Rotation {
/// Minutely Rotation
Minutely,
/// Hourly Rotation
Hourly,
/// Daily Rotation
Daily,
/// No Rotation
Never,
}

impl Rotation {
fn next_date_timestamp(&self, current_date: &OffsetDateTime) -> Option<usize> {
let next_date = match *self {
Rotation::Minutely => *current_date + Duration::minutes(1),
Rotation::Hourly => *current_date + Duration::hours(1),
Rotation::Daily => *current_date + Duration::days(1),
Rotation::Never => return None,
};

Some(self.round_date(&next_date).unix_timestamp() as usize)
}

fn round_date(&self, date: &OffsetDateTime) -> OffsetDateTime {
match *self {
Rotation::Minutely => {
let time = Time::from_hms(date.hour(), date.minute(), 0)
.expect("invalid time; this is a bug in logforth rolling file appender");
date.replace_time(time)
}
Rotation::Hourly => {
let time = Time::from_hms(date.hour(), 0, 0)
.expect("invalid time; this is a bug in logforth rolling file appender");
date.replace_time(time)
}
Rotation::Daily => {
let time = Time::from_hms(0, 0, 0)
.expect("invalid time; this is a bug in logforth rolling file appender");
date.replace_time(time)
}
Rotation::Never => unreachable!("Rotation::Never is impossible to round."),
}
}

fn date_format(&self) -> Vec<format_description::FormatItem<'static>> {
match *self {
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::Never => format_description::parse("[year]-[month]-[day]"),
}
.expect("failed to create a formatter; this is a bug in logforth rolling file appender")
}
}
101 changes: 101 additions & 0 deletions src/append/rolling_file/rotation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Copyright 2024 tison <wander4096@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use time::format_description;
use time::Duration;
use time::OffsetDateTime;
use time::Time;

/// Defines a fixed period for rolling of a log file.
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum Rotation {
/// Minutely Rotation
Minutely,
/// Hourly Rotation
Hourly,
/// Daily Rotation
Daily,
/// No Time Rotation
Never,
}

impl Rotation {
pub fn next_date_timestamp(&self, current_date: &OffsetDateTime) -> Option<usize> {
let next_date = match *self {
Rotation::Minutely => *current_date + Duration::minutes(1),
Rotation::Hourly => *current_date + Duration::hours(1),
Rotation::Daily => *current_date + Duration::days(1),
Rotation::Never => return None,
};

Some(self.round_date(&next_date).unix_timestamp() as usize)
}

fn round_date(&self, date: &OffsetDateTime) -> OffsetDateTime {
match *self {
Rotation::Minutely => {
let time = Time::from_hms(date.hour(), date.minute(), 0)
.expect("invalid time; this is a bug in logforth rolling file appender");
date.replace_time(time)
}
Rotation::Hourly => {
let time = Time::from_hms(date.hour(), 0, 0)
.expect("invalid time; this is a bug in logforth rolling file appender");
date.replace_time(time)
}
Rotation::Daily => {
let time = Time::from_hms(0, 0, 0)
.expect("invalid time; this is a bug in logforth rolling file appender");
date.replace_time(time)
}
Rotation::Never => unreachable!("Rotation::Never is impossible to round."),
}
}

pub fn date_format(&self) -> Vec<format_description::FormatItem<'static>> {
match *self {
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::Never => format_description::parse("[year]-[month]-[day]"),
}
.expect("failed to create a formatter; this is a bug in logforth rolling file appender")
}
}

#[cfg(test)]
mod tests {
use time::macros::datetime;

use super::Rotation;

#[test]
fn test_next_date_timestamp() {
let current_date = datetime!(2024-08-10 17:12:52 +8);

assert_eq!(
Rotation::Minutely.next_date_timestamp(&current_date),
Some(datetime!(2024-08-10 17:13:00 +8).unix_timestamp() as usize)
);
assert_eq!(
Rotation::Hourly.next_date_timestamp(&current_date),
Some(datetime!(2024-08-10 18:00:00 +8).unix_timestamp() as usize)
);
assert_eq!(
Rotation::Daily.next_date_timestamp(&current_date),
Some(datetime!(2024-08-11 00:00:00 +8).unix_timestamp() as usize)
);
assert_eq!(Rotation::Never.next_date_timestamp(&current_date), None);
}
}

0 comments on commit 48ab6df

Please sign in to comment.