Class: Philiprehberger::RateCounter::Counter
- Inherits:
-
Object
- Object
- Philiprehberger::RateCounter::Counter
- Defined in:
- lib/philiprehberger/rate_counter.rb
Overview
A sliding-window rate counter for measuring event throughput
Instance Method Summary collapse
-
#busy?(threshold:, unit: :second) ⇒ Boolean
True when the current rate exceeds
threshold. -
#count ⇒ Integer
Get the current event count within the window.
-
#increment(n = 1) ⇒ self
Increment the counter.
-
#initialize(window: 60) ⇒ Counter
constructor
Create a new rate counter.
-
#peak_rate ⇒ Float
Get the highest rate per second observed since creation or last reset.
-
#rate ⇒ Float
Get the rate of events per second.
-
#rate_per(unit) ⇒ Float
Get the rate projected to a specific time unit.
-
#reset ⇒ void
Reset the counter.
-
#snapshot ⇒ Hash
Return a frozen snapshot of the counter state.
-
#time_since_last ⇒ Float?
Get the number of seconds since the most recent increment.
Constructor Details
#initialize(window: 60) ⇒ Counter
Create a new rate counter
27 28 29 30 31 32 33 34 |
# File 'lib/philiprehberger/rate_counter.rb', line 27 def initialize(window: 60) raise Error, 'Window must be positive' unless window.is_a?(Numeric) && window.positive? @window = window @buckets = [] @peak_rate = 0.0 @mutex = Mutex.new end |
Instance Method Details
#busy?(threshold:, unit: :second) ⇒ Boolean
True when the current rate exceeds threshold.
Useful for back-pressure decisions and threshold-based alerts. Returns
false when no events have been recorded yet.
129 130 131 |
# File 'lib/philiprehberger/rate_counter.rb', line 129 def busy?(threshold:, unit: :second) rate_per(unit) > threshold end |
#count ⇒ Integer
Get the current event count within the window
53 54 55 56 57 58 |
# File 'lib/philiprehberger/rate_counter.rb', line 53 def count @mutex.synchronize do prune count_internal end end |
#increment(n = 1) ⇒ self
Increment the counter
40 41 42 43 44 45 46 47 48 |
# File 'lib/philiprehberger/rate_counter.rb', line 40 def increment(n = 1) @mutex.synchronize do @buckets << [now, n] prune current_rate = rate_internal @peak_rate = current_rate if current_rate > @peak_rate end self end |
#peak_rate ⇒ Float
Get the highest rate per second observed since creation or last reset
73 74 75 |
# File 'lib/philiprehberger/rate_counter.rb', line 73 def peak_rate @mutex.synchronize { @peak_rate } end |
#rate ⇒ Float
Get the rate of events per second
63 64 65 66 67 68 |
# File 'lib/philiprehberger/rate_counter.rb', line 63 def rate @mutex.synchronize do prune rate_internal end end |
#rate_per(unit) ⇒ Float
Get the rate projected to a specific time unit
113 114 115 116 117 118 |
# File 'lib/philiprehberger/rate_counter.rb', line 113 def rate_per(unit) multiplier = RATE_UNITS[unit] raise Error, "Unknown unit: #{unit}. Use :second, :minute, or :hour" unless multiplier rate * multiplier end |
#reset ⇒ void
This method returns an undefined value.
Reset the counter
136 137 138 139 140 141 |
# File 'lib/philiprehberger/rate_counter.rb', line 136 def reset @mutex.synchronize do @buckets.clear @peak_rate = 0.0 end end |
#snapshot ⇒ Hash
Return a frozen snapshot of the counter state
80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/philiprehberger/rate_counter.rb', line 80 def snapshot @mutex.synchronize do prune { count: count_internal, rate: rate_internal, peak_rate: @peak_rate, window: @window, timestamp: Process.clock_gettime(Process::CLOCK_MONOTONIC) }.freeze end end |
#time_since_last ⇒ Float?
Get the number of seconds since the most recent increment
Returns nil if the counter has never been incremented or if all
events have fully expired from the sliding window.
99 100 101 102 103 104 105 106 |
# File 'lib/philiprehberger/rate_counter.rb', line 99 def time_since_last @mutex.synchronize do prune return nil if @buckets.empty? now - @buckets.last[0] end end |