Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for CompositeTrigger #342

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion benches/rotation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ fn mk_config(file_size: u64, file_count: u32) -> log4rs::config::Config {
let roller = policy::compound::roll::fixed_window::FixedWindowRoller::builder()
.build(&roll_pattern, file_count)
.unwrap();
let policy = policy::compound::CompoundPolicy::new(Box::new(trigger), Box::new(roller));
let policy = policy::compound::CompoundPolicy::new(vec![Box::new(trigger)], Box::new(roller));
let file = RollingFileAppender::builder()
.encoder(Box::new(PatternEncoder::new(
"{d(%Y-%m-%d %H:%M:%S.%3f %Z)} {l} [{t} - {T}] {m}{n}",
Expand Down
22 changes: 13 additions & 9 deletions docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,13 @@ my_rolling_appender:
path: "logs/test.log"
policy:
kind: compound
trigger:
kind: size
limit: 1mb
triggers:
- kind: size
limit: 1mb
- kind: time
interval: 1 day
modulate: false
max_random_delay: 0
roller:
kind: fixed_window
base: 1
Expand All @@ -171,7 +175,7 @@ my_rolling_appender:
The new component is the _policy_ field. A policy must have the _kind_ field like most
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
The _triggers_ field is used to dictate when the log file should be rolled. It
supports two types: `size`, and `time`.

For `size`, it require a _limit_ field. The _limit_ field is a string which defines the maximum file size
Expand All @@ -187,9 +191,9 @@ units in bytes, case does not matter:
i.e.

```yml
trigger:
kind: size
limit: 10 mb
triggers:
- kind: size
limit: 10 mb
```

For `time`, it has three field, _interval_, _modulate_ and _max_random_delay_.
Expand Down Expand Up @@ -226,8 +230,8 @@ time.
i.e.

```yml
trigger:
kind: time
triggers:
- kind: time
interval: 1 day
modulate: false
max_random_delay: 0
Expand Down
22 changes: 18 additions & 4 deletions examples/log_to_file_with_rolling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
/// This is the size at which a new file should be created. For the demo it is
/// set to 2KB which is very small and only for demo purposes
const TRIGGER_FILE_SIZE: u64 = 2 * 1024;

const TRIGGER_TIME_CONFIG: (TimeTriggerInterval, bool, u64) =
(TimeTriggerInterval::Day(1), false, 0);
/// Delay between log messages for demo purposes
const TIME_BETWEEN_LOG_MESSAGES: Duration = Duration::from_millis(10);

Expand Down Expand Up @@ -35,7 +36,13 @@ use log4rs::{
append::{
console::{ConsoleAppender, Target},
rolling_file::policy::compound::{
roll::fixed_window::FixedWindowRoller, trigger::size::SizeTrigger, CompoundPolicy,
roll::fixed_window::FixedWindowRoller,
trigger::{
size::SizeTrigger,
time::{TimeTrigger, TimeTriggerInterval},
Trigger,
},
CompoundPolicy,
},
},
config::{Appender, Config, Root},
Expand All @@ -50,12 +57,19 @@ fn main() -> Result<(), SetLoggerError> {
let stderr = ConsoleAppender::builder().target(Target::Stderr).build();

// Create a policy to use with the file logging
let trigger = SizeTrigger::new(TRIGGER_FILE_SIZE);
let trigger_size = SizeTrigger::new(TRIGGER_FILE_SIZE);
let trigger_time = TimeTrigger::new(
TRIGGER_TIME_CONFIG.0,
TRIGGER_TIME_CONFIG.1,
TRIGGER_TIME_CONFIG.2,
);
let trigger: Vec<Box<dyn Trigger>> = vec![Box::new(trigger_size), Box::new(trigger_time)];

let roller = FixedWindowRoller::builder()
.base(0) // Default Value (line not needed unless you want to change from 0 (only here for demo purposes)
.build(ARCHIVE_PATTERN, LOG_FILE_COUNT) // Roll based on pattern and max 3 archive files
.unwrap();
let policy = CompoundPolicy::new(Box::new(trigger), Box::new(roller));
let policy = CompoundPolicy::new(trigger, Box::new(roller));

// Logging to log file. (with rolling)
let logfile = log4rs::append::rolling_file::RollingFileAppender::builder()
Expand Down
64 changes: 33 additions & 31 deletions examples/sample_config.yml
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
appenders:
stdout:
kind: console
encoder:
pattern: "{d(%+)(utc)} [{f}:{L}] {h({l})} {M}:{m}{n}"
filters:
- kind: threshold
level: info
file:
kind: file
path: "log/file.log"
encoder:
pattern: "[{d(%Y-%m-%dT%H:%M:%S%.6f)} {h({l}):<5.5} {M}] {m}{n}"
rollingfile:
kind: rolling_file
path: "log/rolling_file.log"
encoder:
pattern: "[{d(%Y-%m-%dT%H:%M:%S%.6f)} {h({l}):<5.5} {M}] {m}{n}"
policy:
trigger:
kind: time
interval: 1 minute
roller:
kind: fixed_window
pattern: "log/old-rolling_file-{}.log"
base: 0
count: 2
stdout:
kind: console
encoder:
pattern: "{d(%+)(utc)} [{f}:{L}] {h({l})} {M}:{m}{n}"
filters:
- kind: threshold
level: info
file:
kind: file
path: "log/file.log"
encoder:
pattern: "[{d(%Y-%m-%dT%H:%M:%S%.6f)} {h({l}):<5.5} {M}] {m}{n}"
rollingfile:
kind: rolling_file
path: "log/rolling_file.log"
encoder:
pattern: "[{d(%Y-%m-%dT%H:%M:%S%.6f)} {h({l}):<5.5} {M}] {m}{n}"
policy:
triggers:
- kind: time
interval: 1 day
- kind: size
limit: 2 mb
roller:
kind: fixed_window
pattern: "log/old-rolling_file-{}.log"
base: 0
count: 2
root:
level: info
appenders:
- stdout
- file
- rollingfile
level: info
appenders:
- stdout
- file
- rollingfile
50 changes: 25 additions & 25 deletions src/append/rolling_file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,9 @@ impl RollingFileAppenderBuilder {
///
/// # The remainder of the configuration is passed along to the policy's
/// # deserializer, and will vary based on the kind of policy.
/// trigger:
/// kind: size
/// limit: 10 mb
/// triggers:
/// - kind: size
/// limit: 10 mb
///
/// roller:
/// kind: delete
Expand Down Expand Up @@ -385,28 +385,28 @@ mod test {
let config = format!(
"
appenders:
foo:
kind: rolling_file
path: {0}/foo.log
policy:
trigger:
kind: time
interval: 2 minutes
roller:
kind: delete
bar:
kind: rolling_file
path: {0}/foo.log
policy:
kind: compound
trigger:
kind: size
limit: 5 mb
roller:
kind: fixed_window
pattern: '{0}/foo.log.{{}}'
base: 1
count: 5
foo:
kind: rolling_file
path: {0}/foo.log
policy:
triggers:
- kind: time
interval: 2 minutes
roller:
kind: delete
bar:
kind: rolling_file
path: {0}/foo.log
policy:
kind: compound
triggers:
- kind: size
limit: 5 mb
roller:
kind: fixed_window
pattern: '{0}/foo.log.{{}}'
base: 1
count: 5
",
dir.path().display()
);
Expand Down
44 changes: 30 additions & 14 deletions src/append/rolling_file/policy/compound/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub mod trigger;
#[derive(Clone, Eq, PartialEq, Hash, Debug, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub struct CompoundPolicyConfig {
trigger: Trigger,
triggers: Vec<Trigger>,
roller: Roller,
}

Expand Down Expand Up @@ -81,35 +81,46 @@ impl<'de> serde::Deserialize<'de> for Roller {
}
}

/// A rolling policy which delegates to a "trigger" and "roller".
/// A rolling policy which delegates to a "triggers" and "roller".
///
/// The trigger determines if the log file should roll, for example, by checking
/// the size of the file. The roller processes the old log file, for example,
/// by compressing it and moving it to a different location.
#[derive(Debug)]
pub struct CompoundPolicy {
trigger: Box<dyn trigger::Trigger>,
triggers: Vec<Box<dyn trigger::Trigger>>,
roller: Box<dyn Roll>,
}

impl CompoundPolicy {
/// Creates a new `CompoundPolicy`.
pub fn new(trigger: Box<dyn trigger::Trigger>, roller: Box<dyn Roll>) -> CompoundPolicy {
CompoundPolicy { trigger, roller }
pub fn new(triggers: Vec<Box<dyn trigger::Trigger>>, roller: Box<dyn Roll>) -> CompoundPolicy {
CompoundPolicy { triggers, roller }
}
}

impl Policy for CompoundPolicy {
fn process(&self, log: &mut LogFile) -> anyhow::Result<()> {
if self.trigger.trigger(log)? {
let mut is_trigger = false;
for trigger in &self.triggers {
if trigger.trigger(log)? {
is_trigger = true;
}
}
if is_trigger {
log.roll();
self.roller.roll(log.path())?;
}
Ok(())
}

fn is_pre_process(&self) -> bool {
self.trigger.is_pre_process()
for trigger in &self.triggers {
if trigger.is_pre_process() {
return true;
}
}
false
}
}

Expand All @@ -121,14 +132,14 @@ impl Policy for CompoundPolicy {
/// kind: compound
///
/// # The trigger, which determines when the log will roll over. Required.
/// trigger:
/// triggers:
///
/// # Identifies which trigger is to be used. Required.
/// kind: size
/// - kind: size
///
/// # The remainder of the configuration is passed to the trigger's
/// # deserializer, and will vary based on the kind of trigger.
/// limit: 10 mb
/// # The remainder of the configuration is passed to the trigger's
/// # deserializer, and will vary based on the kind of trigger.
/// limit: 10 mb
///
/// # The roller, which processes the old log file. Required.
/// roller:
Expand All @@ -154,8 +165,13 @@ impl Deserialize for CompoundPolicyDeserializer {
config: CompoundPolicyConfig,
deserializers: &Deserializers,
) -> anyhow::Result<Box<dyn Policy>> {
let trigger = deserializers.deserialize(&config.trigger.kind, config.trigger.config)?;
let mut triggers = Vec::new();
for config_trigger in &config.triggers {
let trigger =
deserializers.deserialize(&config_trigger.kind, config_trigger.config.clone())?;
triggers.push(trigger);
}
let roller = deserializers.deserialize(&config.roller.kind, config.roller.config)?;
Ok(Box::new(CompoundPolicy::new(trigger, roller)))
Ok(Box::new(CompoundPolicy::new(triggers, roller)))
}
}
2 changes: 1 addition & 1 deletion src/append/rolling_file/policy/compound/trigger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ pub trait Trigger: fmt::Debug + Send + Sync + 'static {
#[cfg(feature = "config_parsing")]
impl Deserializable for dyn Trigger {
fn name() -> &'static str {
"trigger"
"triggers"
}
}
Loading
Loading