Class: Hyperion::Metrics
- Inherits:
-
Object
- Object
- Hyperion::Metrics
- Defined in:
- lib/hyperion/metrics.rb
Overview
Lock-free per-thread counters. Each worker thread mutates its own Hash on the hot path — no mutex acquire/release on every increment, no contention across the thread pool. ‘snapshot` aggregates lazily across all threads that have ever incremented (one short mutex section, only taken when the operator asks for stats).
Reset semantics: counters monotonically increase. Operators that want rate-of-change should snapshot, sleep, snapshot, diff.
Public API:
Hyperion.stats -> Hash with all current values across all threads.
Instance Method Summary collapse
- #decrement(key, by = 1) ⇒ Object
-
#increment(key, by = 1) ⇒ Object
Hot path: one TLS lookup + one hash op.
- #increment_status(code) ⇒ Object
-
#initialize ⇒ Metrics
constructor
A new instance of Metrics.
-
#reset! ⇒ Object
Tests can call .reset! between examples to avoid cross-spec leakage.
- #snapshot ⇒ Object
Constructor Details
#initialize ⇒ Metrics
Returns a new instance of Metrics.
16 17 18 19 20 21 22 |
# File 'lib/hyperion/metrics.rb', line 16 def initialize @threads = Set.new @threads_mutex = Mutex.new # Each Metrics instance has its own thread-local key so spec runs that # build fresh Metrics objects don't share state across examples. @thread_key = :"__hyperion_metrics_#{object_id}__" end |
Instance Method Details
#decrement(key, by = 1) ⇒ Object
30 31 32 |
# File 'lib/hyperion/metrics.rb', line 30 def decrement(key, by = 1) increment(key, -by) end |
#increment(key, by = 1) ⇒ Object
Hot path: one TLS lookup + one hash op. No mutex.
25 26 27 28 |
# File 'lib/hyperion/metrics.rb', line 25 def increment(key, by = 1) counters = Thread.current[@thread_key] ||= register_thread_counters counters[key] += by end |
#increment_status(code) ⇒ Object
34 35 36 |
# File 'lib/hyperion/metrics.rb', line 34 def increment_status(code) increment(:"responses_#{code}") end |
#reset! ⇒ Object
Tests can call .reset! between examples to avoid cross-spec leakage.
54 55 56 57 58 |
# File 'lib/hyperion/metrics.rb', line 54 def reset! @threads_mutex.synchronize do @threads.each { |t| t[@thread_key]&.clear } end end |
#snapshot ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/hyperion/metrics.rb', line 38 def snapshot result = Hash.new(0) @threads_mutex.synchronize do @threads.delete_if { |t| !t.alive? } @threads.each do |t| counters = t[@thread_key] next unless counters counters.each { |k, v| result[k] += v } end end result.default = nil result end |