factor out common loop that tests a sequence of limiters

This commit is contained in:
Chris Beck
2025-12-06 19:45:33 -07:00
parent 225b308a26
commit 12f0c99ef9
4 changed files with 27 additions and 20 deletions
+3 -6
View File
@@ -1,5 +1,5 @@
use super::{
LimitResult, Limiter, LimiterSet, SignalAlertMessage, Summary,
LimitResult, Limiter, LimiterSet, SignalAlertMessage, Summary, evaluate_limiter_sequence,
log_buffer::LogBuffer,
route::{Destination, Limit, Route},
};
@@ -262,11 +262,8 @@ impl LogHandler {
};
// At least one route passed, now check overall limits
for (idx, (filter, limiter)) in self.overall_limits.iter().enumerate() {
// Only evaluate the limiter if the message matches the filter
if filter.matches(log_msg) && !limiter.evaluate(log_msg) {
return Err(SuppressionReason::Overall(LimitResult::OverallLimiter(idx)));
}
if let Err(i) = evaluate_limiter_sequence(&self.overall_limits, log_msg) {
return Err(SuppressionReason::Overall(LimitResult::OverallLimiter(i)));
}
// All checks passed
+1 -1
View File
@@ -39,7 +39,7 @@ mod rate_limiter_set;
pub use rate_limiter_set::{LimitResult, LimiterSet};
mod route;
pub use route::{Destination, Limit, Route};
pub use route::{Destination, Limit, Route, evaluate_limiter_sequence};
pub use crate::rate_limiter::{Limiter, RateThreshold};
+6 -12
View File
@@ -1,5 +1,6 @@
//! Rate limiter set for managing per-route rate limiting.
use super::evaluate_limiter_sequence;
use crate::{
concurrent_map::LazyMap,
log_message::{LogFilter, LogMessage, Origin},
@@ -54,13 +55,9 @@ impl LimiterSet {
pub fn evaluate(&self, log_msg: &LogMessage, origin: &Origin) -> LimitResult {
// Check per-origin limiters
let origin_result = self.limiters.get(origin, |origin_limiters| {
for (i, (filter, limiter)) in origin_limiters.iter().enumerate() {
// Only evaluate the limiter if the message matches the filter
if filter.matches(log_msg) && !limiter.evaluate(log_msg) {
return Some(LimitResult::Limiter(i));
}
}
None
evaluate_limiter_sequence(origin_limiters, log_msg)
.err()
.map(LimitResult::Limiter)
});
if let Some(result) = origin_result {
@@ -68,11 +65,8 @@ impl LimiterSet {
}
// Check global limiters
for (i, (filter, limiter)) in self.global_limiters.iter().enumerate() {
// Only evaluate the limiter if the message matches the filter
if filter.matches(log_msg) && !limiter.evaluate(log_msg) {
return LimitResult::GlobalLimiter(i);
}
if let Err(i) = evaluate_limiter_sequence(&self.global_limiters, log_msg) {
return LimitResult::GlobalLimiter(i);
}
LimitResult::Passed
+17 -1
View File
@@ -5,11 +5,27 @@
use super::LimiterSet;
use crate::{
log_message::{Level, LogFilter},
log_message::{Level, LogFilter, LogMessage},
rate_limiter::{Limiter, RateThreshold},
};
use serde::Deserialize;
/// Evaluate a sequence of (filter, limiter) pairs against a log message.
///
/// Returns `Ok(())` if no limiter blocks the message.
/// Returns `Err(index)` if the limiter at `index` blocked the message.
pub fn evaluate_limiter_sequence(
seq: &[(LogFilter, Limiter)],
log_msg: &LogMessage,
) -> Result<(), usize> {
for (i, (filter, limiter)) in seq.iter().enumerate() {
if filter.matches(log_msg) && !limiter.evaluate(log_msg) {
return Err(i);
}
}
Ok(())
}
/// A rate limit rule for suppressing repeated alerts.
///
/// Combines a filter to match specific log messages with a rate threshold.