Skip to content

Commit

Permalink
feat!(trigger): add support for CompositeTrigger
Browse files Browse the repository at this point in the history
  • Loading branch information
Dirreke committed Feb 2, 2024
1 parent 6c6ace0 commit 585cbec
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 99 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
rust_versions: ["stable", "1.67"]
rust_versions: ["stable", "1.69"]
os: [ubuntu-latest, windows-latest]
steps:
- name: Checkout the source code
Expand Down Expand Up @@ -63,7 +63,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
rust_versions: ["stable", "1.67"]
rust_versions: ["stable", "1.69"]
steps:
- name: Checkout the source code
uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ repository = "https://github.com/estk/log4rs"
readme = "README.md"
keywords = ["log", "logger", "logging", "log4"]
edition = "2018"
rust-version = "1.67"
rust-version = "1.69"

[features]
default = ["all_components", "config_parsing", "yaml_format"]
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![crates.io](https://img.shields.io/crates/v/log4rs.svg)](https://crates.io/crates/log4rs)
[![License: MIT OR Apache-2.0](https://img.shields.io/crates/l/clippy.svg)](#license)
![CI](https://github.com/estk/log4rs/workflows/CI/badge.svg)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.67+-green.svg)](https://github.com/estk/log4rs#rust-version-requirements)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.69+-green.svg)](https://github.com/estk/log4rs#rust-version-requirements)

log4rs is a highly configurable logging framework modeled after Java's Logback
and log4j libraries.
Expand Down Expand Up @@ -71,7 +71,7 @@ fn main() {

## Rust Version Requirements

1.67
1.69

## Building for Dev

Expand Down
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
28 changes: 16 additions & 12 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,11 +230,11 @@ time.
i.e.

```yml
trigger:
kind: time
interval: 1 day
modulate: false
max_random_delay: 0
triggers:
- kind: time
interval: 1 day
modulate: false
max_random_delay: 0
```

The _roller_ field supports two types: delete, and fixed_window. The delete
Expand Down
21 changes: 17 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,7 @@
/// 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_INTERVAL: TimeTriggerInterval = TimeTriggerInterval::Day(1);
/// Delay between log messages for demo purposes
const TIME_BETWEEN_LOG_MESSAGES: Duration = Duration::from_millis(10);

Expand Down Expand Up @@ -35,7 +35,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, TimeTriggerConfig, TimeTriggerInterval},
Trigger,
},
CompoundPolicy,
},
},
config::{Appender, Config, Root},
Expand All @@ -50,12 +56,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_config = TimeTriggerConfig {
interval: TRIGGER_TIME_INTERVAL,
..Default::default()
};
let trigger_time = TimeTrigger::new(trigger_time_config);
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
62 changes: 31 additions & 31 deletions examples/sample_config.yml
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
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 minute
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;
}
}
return 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

0 comments on commit 585cbec

Please sign in to comment.