philiprehberger-rate_counter

Tests Gem Version Last updated

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:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT