philiprehberger-rate_counter
Sliding-window rate counter for measuring event throughput in real-time
Requirements
- Ruby >= 3.1
Installation
Add to your Gemfile:
gem "philiprehberger-rate_counter"
Or install directly:
gem install philiprehberger-rate_counter
Usage
require "philiprehberger/rate_counter"
counter = Philiprehberger::RateCounter::Counter.new(window: 60)
counter.increment
counter.increment(5)
counter.rate # => events per second
counter.count # => total events in window
counter.rate_per(:minute) # => events per minute
Peak Rate and Snapshots
require "philiprehberger/rate_counter"
counter = Philiprehberger::RateCounter::Counter.new(window: 60)
100.times { counter.increment }
counter.peak_rate # => highest rate per second observed
counter.snapshot # => { count: 100, rate: 16.7, peak_rate: 16.7, window: 60, timestamp: ... }
registry = Philiprehberger::RateCounter::Registry.new
registry[:api].increment(50)
registry.snapshot # => { api: { count: 50, rate: ..., ... } }
Last activity
Check how long ago the counter last recorded an event:
require "philiprehberger/rate_counter"
counter = Philiprehberger::RateCounter::Counter.new(window: 60)
counter.time_since_last # => nil (never incremented)
counter.increment
counter.time_since_last # => 0.0001 (seconds since last increment)
Returns nil when the counter has never been incremented or when all events
have expired from the sliding window.
Threshold Check
Quickly decide whether the counter is "busy" based on a rate threshold — useful for back-pressure decisions and alert wiring.
counter = Philiprehberger::RateCounter::Counter.new(window: 60)
120.times { counter.increment }
counter.busy?(threshold: 1) # => true (2 events/second > 1)
counter.busy?(threshold: 100, unit: :minute) # => true (120 events/min > 100)
Registry
Manage multiple named counters with a shared window configuration:
reg = Philiprehberger::RateCounter::Registry.new(window: 60)
reg[:requests].increment
reg[:errors].increment
reg[:requests].rate # => request rate
reg[:errors].count # => error count in window
reg.names # => [:requests, :errors]
reg.reset_all # => reset all counters
API
Philiprehberger::RateCounter::Counter
| Method | Description |
|---|---|
.new(window:) |
Create a counter with a sliding window (seconds) |
#increment(n) |
Record n events (default: 1) |
#rate |
Events per second over the window |
#count |
Total events within the window |
#rate_per(unit) |
Projected rate per :second, :minute, or :hour |
#busy?(threshold:, unit: :second) |
True when current rate exceeds threshold for the given unit |
#peak_rate |
Highest rate per second observed since creation or last reset |
#snapshot |
Frozen hash with count, rate, peak_rate, window, and timestamp |
#time_since_last |
Seconds since the most recent increment, or nil if the window is empty |
#reset |
Clear all recorded events |
Philiprehberger::RateCounter::Registry
| Method | Description |
|---|---|
.new(window:) |
Create a registry with a default window for new counters |
#[](name) |
Access or create a named counter |
#names |
List all registered counter names |
#size |
Number of registered counters |
#snapshot |
Frozen hash of name to counter snapshot |
#reset_all |
Reset all counters |
Development
bundle install
bundle exec rspec
bundle exec rubocop
Support
If you find this project useful: