diff --git a/signal-gateway/src/gateway/log_handler.rs b/signal-gateway/src/gateway/log_handler.rs index 362c12b..adbe934 100644 --- a/signal-gateway/src/gateway/log_handler.rs +++ b/signal-gateway/src/gateway/log_handler.rs @@ -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 diff --git a/signal-gateway/src/gateway/mod.rs b/signal-gateway/src/gateway/mod.rs index 2693228..c529d6a 100644 --- a/signal-gateway/src/gateway/mod.rs +++ b/signal-gateway/src/gateway/mod.rs @@ -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}; diff --git a/signal-gateway/src/gateway/rate_limiter_set.rs b/signal-gateway/src/gateway/rate_limiter_set.rs index 9ae53d2..a7eaded 100644 --- a/signal-gateway/src/gateway/rate_limiter_set.rs +++ b/signal-gateway/src/gateway/rate_limiter_set.rs @@ -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 diff --git a/signal-gateway/src/gateway/route.rs b/signal-gateway/src/gateway/route.rs index 22e0fb3..18a6a87 100644 --- a/signal-gateway/src/gateway/route.rs +++ b/signal-gateway/src/gateway/route.rs @@ -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.