Class: RailsErrorDashboard::Services::NotificationThrottler
- Inherits:
-
Object
- Object
- RailsErrorDashboard::Services::NotificationThrottler
- Defined in:
- lib/rails_error_dashboard/services/notification_throttler.rb
Overview
Pure algorithm: Throttle error notifications to prevent alert fatigue
Checks severity minimum, per-error cooldown, and threshold milestones. Uses in-memory cache (same pattern as BaselineAlertThrottler). Thread-safe via Mutex. Fail-open: returns true on any error.
Constant Summary collapse
- SEVERITY_RANK =
Severity levels ranked from lowest to highest
{ low: 0, medium: 1, high: 2, critical: 3 }.freeze
Class Method Summary collapse
-
.cleanup!(max_age_hours: 24) ⇒ Object
Remove old entries to prevent memory growth.
-
.clear! ⇒ Object
Clear all throttle state (for testing).
-
.record_notification(error_log) ⇒ Object
Record that a notification was sent for this error.
-
.severity_meets_minimum?(error_log) ⇒ Boolean
Does the error’s severity meet the configured minimum?.
-
.should_notify?(error_log) ⇒ Boolean
Should we send a notification for this error? Checks: severity minimum + cooldown period.
-
.threshold_reached?(error_log) ⇒ Boolean
Has the error’s occurrence count reached a configured threshold milestone?.
Class Method Details
.cleanup!(max_age_hours: 24) ⇒ Object
Remove old entries to prevent memory growth
80 81 82 83 84 85 86 |
# File 'lib/rails_error_dashboard/services/notification_throttler.rb', line 80 def cleanup!(max_age_hours: 24) cutoff_time = max_age_hours.hours.ago @mutex.synchronize do @last_notification_times.delete_if { |_, time| time < cutoff_time } end end |
.clear! ⇒ Object
Clear all throttle state (for testing)
72 73 74 75 76 |
# File 'lib/rails_error_dashboard/services/notification_throttler.rb', line 72 def clear! @mutex.synchronize do @last_notification_times.clear end end |
.record_notification(error_log) ⇒ Object
Record that a notification was sent for this error
61 62 63 64 65 66 67 68 69 |
# File 'lib/rails_error_dashboard/services/notification_throttler.rb', line 61 def record_notification(error_log) key = error_log.error_hash @mutex.synchronize do @last_notification_times[key] = Time.current end rescue => e RailsErrorDashboard::Logger.debug("[RailsErrorDashboard] NotificationThrottler.record_notification failed: #{e.}") end |
.severity_meets_minimum?(error_log) ⇒ Boolean
Does the error’s severity meet the configured minimum?
35 36 37 38 39 40 41 42 43 44 |
# File 'lib/rails_error_dashboard/services/notification_throttler.rb', line 35 def severity_meets_minimum?(error_log) config = RailsErrorDashboard.configuration minimum = config.notification_minimum_severity || :low severity = SeverityClassifier.classify(error_log.error_type) (SEVERITY_RANK[severity] || 0) >= (SEVERITY_RANK[minimum] || 0) rescue => e RailsErrorDashboard::Logger.debug("[RailsErrorDashboard] NotificationThrottler.severity_meets_minimum? failed: #{e.}") true end |
.should_notify?(error_log) ⇒ Boolean
Should we send a notification for this error? Checks: severity minimum + cooldown period
22 23 24 25 26 27 28 29 30 |
# File 'lib/rails_error_dashboard/services/notification_throttler.rb', line 22 def should_notify?(error_log) return false unless severity_meets_minimum?(error_log) cooldown_ok?(error_log) rescue => e # Fail-open: if throttler breaks, allow notification RailsErrorDashboard::Logger.debug("[RailsErrorDashboard] NotificationThrottler.should_notify? failed: #{e.}") true end |
.threshold_reached?(error_log) ⇒ Boolean
Has the error’s occurrence count reached a configured threshold milestone?
49 50 51 52 53 54 55 56 57 |
# File 'lib/rails_error_dashboard/services/notification_throttler.rb', line 49 def threshold_reached?(error_log) thresholds = RailsErrorDashboard.configuration.notification_threshold_alerts return false if thresholds.nil? || thresholds.empty? thresholds.include?(error_log.occurrence_count) rescue => e RailsErrorDashboard::Logger.debug("[RailsErrorDashboard] NotificationThrottler.threshold_reached? failed: #{e.}") false end |