Skip to content

Commit

Permalink
Add trigger onstartup (#343)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dirreke authored Apr 1, 2024
1 parent 8ab1b34 commit f688e38
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ delete_roller = []
fixed_window_roller = []
size_trigger = []
time_trigger = ["rand"]
onstartup_trigger = []
json_encoder = ["serde", "serde_json", "chrono", "log-mdc", "log/serde", "thread-id"]
pattern_encoder = ["chrono", "log-mdc", "thread-id"]
ansi_writer = []
Expand All @@ -43,6 +44,7 @@ all_components = [
"fixed_window_roller",
"size_trigger",
"time_trigger",
"onstartup_trigger",
"json_encoder",
"pattern_encoder",
"threshold_filter"
Expand Down
12 changes: 11 additions & 1 deletion docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ The new component is the _policy_ field. A policy must have the _kind_ field lik
other components, the default (and only supported) policy is `kind: compound`.

The _trigger_ field is used to dictate when the log file should be rolled. It
supports two types: `size`, and `time`.
supports three types: `size`, `time` and `onstartup`.

For `size`, it require a _limit_ field. The _limit_ field is a string which defines the maximum file size
prior to a rolling of the file. The limit field requires one of the following
Expand Down Expand Up @@ -233,6 +233,16 @@ trigger:
max_random_delay: 0
```

For `onstartup`, it has an optional field, _min_size_. It indicates the minimum size the file must have to roll over. A size of zero will cause a roll over no matter what the file size is. The default value is 1, which will prevent rolling over an empty file.

i.e.

```yml
trigger:
kind: onstartup
min_size: 1
```

The _roller_ field supports two types: delete, and fixed_window. The delete
roller does not take any other configuration fields. The fixed_window roller
supports three fields: pattern, base, and count. The most current log file will
Expand Down
3 changes: 3 additions & 0 deletions src/append/rolling_file/policy/compound/trigger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ pub mod size;
#[cfg(feature = "time_trigger")]
pub mod time;

#[cfg(feature = "onstartup_trigger")]
pub mod onstartup;

/// A trait which identifies if the active log file should be rolled over.
pub trait Trigger: fmt::Debug + Send + Sync + 'static {
/// Determines if the active log file should be rolled over.
Expand Down
119 changes: 119 additions & 0 deletions src/append/rolling_file/policy/compound/trigger/onstartup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
//! The OnStartUp trigger.
//!
//! Requires the `onstartup_trigger` feature.

use std::sync::Once;

use crate::append::rolling_file::{policy::compound::trigger::Trigger, LogFile};

#[cfg(feature = "config_parsing")]
use crate::config::{Deserialize, Deserializers};

/// Configuration for the onstartup trigger.
#[cfg(feature = "config_parsing")]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub struct OnStartUpTriggerConfig {
#[serde(default = "default_min_size")]
min_size: u64,
}

#[cfg(feature = "config_parsing")]
fn default_min_size() -> u64 {
1
}

/// A trigger which rolls the log on startup.
#[derive(Debug)]
pub struct OnStartUpTrigger {
min_size: u64,
initial: Once,
}

impl OnStartUpTrigger {
/// Returns a new trigger which rolls the log on startup.
pub fn new(min_size: u64) -> OnStartUpTrigger {
OnStartUpTrigger {
min_size,
initial: Once::new(),
}
}
}

impl Trigger for OnStartUpTrigger {
fn trigger(&self, file: &LogFile) -> anyhow::Result<bool> {
let mut result = false;
self.initial.call_once(|| {
if file.len_estimate() >= self.min_size {
result = true;
}
});
Ok(result)
}

fn is_pre_process(&self) -> bool {
true
}
}

/// A deserializer for the `OnStartUpTrigger`.
///
/// # Configuration
///
/// ```yaml
/// kind: onstartup
///
/// ```
#[cfg(feature = "config_parsing")]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
pub struct OnStartUpTriggerDeserializer;

#[cfg(feature = "config_parsing")]
impl Deserialize for OnStartUpTriggerDeserializer {
type Trait = dyn Trigger;

type Config = OnStartUpTriggerConfig;

fn deserialize(
&self,
config: OnStartUpTriggerConfig,
_: &Deserializers,
) -> anyhow::Result<Box<dyn Trigger>> {
Ok(Box::new(OnStartUpTrigger::new(config.min_size)))
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn pre_process() {
let trigger = OnStartUpTrigger::new(0);
assert!(trigger.is_pre_process());
}

fn trigger_with_file_size(file_size: u64) -> (bool, bool) {
let file = tempfile::tempdir().unwrap();
let logfile = LogFile {
writer: &mut None,
path: file.path(),
len: file_size,
};

let trigger = OnStartUpTrigger::new(1); // default
let result1 = trigger.trigger(&logfile).unwrap();
let result2 = trigger.trigger(&logfile).unwrap();
(result1, result2)
}

#[test]
fn trigger() {
// When the file size < min_size, the trigger should return false.
assert_eq!(trigger_with_file_size(0), (false, false));
// When the file size == min_size, the trigger should return true for the first time.
assert_eq!(trigger_with_file_size(1), (true, false));
// When the file size >= min_size, the trigger should return true for the first time.
assert_eq!(trigger_with_file_size(2), (true, false));
}
}
8 changes: 8 additions & 0 deletions src/config/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,12 @@ impl Default for Deserializers {
append::rolling_file::policy::compound::trigger::time::TimeTriggerDeserializer,
);

#[cfg(feature = "onstartup_trigger")]
d.insert(
"onstartup",
append::rolling_file::policy::compound::trigger::onstartup::OnStartUpTriggerDeserializer,
);

#[cfg(feature = "json_encoder")]
d.insert("json", encode::json::JsonEncoderDeserializer);

Expand Down Expand Up @@ -265,6 +271,8 @@ impl Deserializers {
/// * Requires the `size_trigger` feature.
/// * "time" -> `TimeTriggerDeserializer`
/// * Requires the `time_trigger` feature.
/// * "onstartup" -> `OnStartUpTriggerDeserializer`
/// * Requires the `onstartup_trigger` feature.
pub fn new() -> Deserializers {
Deserializers::default()
}
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
//! - Triggers
//! - [size](append/rolling_file/policy/compound/trigger/size/struct.SizeTriggerDeserializer.html#configuration): requires the `size_trigger` feature
//! - [time](append/rolling_file/policy/compound/trigger/tine/struct.TimeTriggerDeserializer.html#configuration): requires the `time_trigger` feature
//! - [onstartup](append/rolling_file/policy/compound/trigger/tine/struct.OnStartUpTriggerDeserializer.html#configuration): requires the `onstartup_trigger` feature
//!
//! ## Encoders
//!
Expand Down

0 comments on commit f688e38

Please sign in to comment.