Class: CMDx::Telemetry
- Inherits:
-
Object
- Object
- CMDx::Telemetry
- Defined in:
- lib/cmdx/telemetry.rb
Overview
Pub/sub for runtime lifecycle and infrastructure events (see EVENTS). Subscribers are callables receiving an Event data object. Telemetry.emit dispatches only when subscribers are registered so telemetry has zero cost when unused.
Defined Under Namespace
Classes: Event
Constant Summary collapse
- EVENTS =
Lifecycle and infrastructure event names the runtime and store-backed helpers emit.
%i[ task_started task_deprecated task_retried task_rolled_back task_executed lock_acquired lock_busy idempotency_claimed idempotency_completed idempotency_duplicate circuit_open circuit_tripped circuit_reset rate_limit_admitted rate_limit_exceeded ].freeze
Instance Attribute Summary collapse
-
#registry ⇒ Object
readonly
Returns the value of attribute registry.
Class Method Summary collapse
-
.emit(task, name, root: false, **payload) ⇒ void
Dispatches
payloadwhentask's telemetry registry has subscribers forname.
Instance Method Summary collapse
-
#count ⇒ Integer
Total subscribers across all events.
-
#emit(event, payload) ⇒ void
Dispatches
payloadto every subscriber ofevent. - #empty? ⇒ Boolean
-
#initialize ⇒ Telemetry
constructor
A new instance of Telemetry.
- #initialize_copy(source) ⇒ void
- #lookup(event) ⇒ #call
-
#size ⇒ Integer
Number of subscribed events.
-
#subscribe(event, callable = nil, &block) {|evt| ... } ⇒ Telemetry
Registers a subscriber for
event. -
#subscribed?(event) ⇒ Boolean
True when at least one subscriber exists for
event. -
#unsubscribe(event, callable) ⇒ Telemetry
Removes a previously registered subscriber.
Constructor Details
#initialize ⇒ Telemetry
Returns a new instance of Telemetry.
69 70 71 |
# File 'lib/cmdx/telemetry.rb', line 69 def initialize @registry = {} end |
Instance Attribute Details
#registry ⇒ Object (readonly)
Returns the value of attribute registry.
67 68 69 |
# File 'lib/cmdx/telemetry.rb', line 67 def registry @registry end |
Class Method Details
.emit(task, name, root: false, **payload) ⇒ void
This method returns an undefined value.
Dispatches payload when task's telemetry registry has subscribers
for name. No-op when nothing is subscribed.
57 58 59 60 61 62 63 |
# File 'lib/cmdx/telemetry.rb', line 57 def emit(task, name, root: false, **payload) telemetry = task.class.telemetry return unless telemetry.subscribed?(name) event = Event.build(task, name, root:, payload:) telemetry.emit(name, event) end |
Instance Method Details
#count ⇒ Integer
Returns total subscribers across all events.
161 162 163 |
# File 'lib/cmdx/telemetry.rb', line 161 def count registry.each_value.sum(&:size) end |
#emit(event, payload) ⇒ void
This method returns an undefined value.
Dispatches payload to every subscriber of event. No-op when there
are no subscribers.
171 172 173 174 175 176 177 178 |
# File 'lib/cmdx/telemetry.rb', line 171 def emit(event, payload) return if empty? subscribers = lookup(event) return if subscribers.nil? || subscribers.empty? subscribers.each { |callable| callable.call(payload) } end |
#empty? ⇒ Boolean
151 152 153 |
# File 'lib/cmdx/telemetry.rb', line 151 def empty? registry.empty? end |
#initialize_copy(source) ⇒ void
This method returns an undefined value.
75 76 77 |
# File 'lib/cmdx/telemetry.rb', line 75 def initialize_copy(source) @registry = source.registry.transform_values(&:dup) end |
#lookup(event) ⇒ #call
141 142 143 144 145 146 147 148 |
# File 'lib/cmdx/telemetry.rb', line 141 def lookup(event) registry[event] || begin raise UnknownEntryError, <<~MSG.chomp unknown telemetry event #{event.inspect}; registered: #{registry.keys.inspect}. See https://drexed.github.io/cmdx/configuration/#telemetry MSG end end |
#size ⇒ Integer
Returns number of subscribed events.
156 157 158 |
# File 'lib/cmdx/telemetry.rb', line 156 def size registry.size end |
#subscribe(event, callable = nil, &block) {|evt| ... } ⇒ Telemetry
Registers a subscriber for event.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/cmdx/telemetry.rb', line 88 def subscribe(event, callable = nil, &block) subscriber = callable || block if callable && block raise ArgumentError, "subscriber: provide either a callable or a block, not both" elsif !subscriber.respond_to?(:call) raise ArgumentError, <<~MSG.chomp subscriber must respond to #call (got #{subscriber.class}). See https://drexed.github.io/cmdx/configuration/#telemetry MSG elsif !EVENTS.include?(event) raise ArgumentError, <<~MSG.chomp unknown telemetry event #{event.inspect}, must be one of #{EVENTS.inspect}. See https://drexed.github.io/cmdx/configuration/#telemetry MSG end (registry[event] ||= []) << subscriber self end |
#subscribed?(event) ⇒ Boolean
Returns true when at least one subscriber exists for event.
134 135 136 |
# File 'lib/cmdx/telemetry.rb', line 134 def subscribed?(event) registry.key?(event) end |
#unsubscribe(event, callable) ⇒ Telemetry
Removes a previously registered subscriber. Drops the event entry entirely when no subscribers remain.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/cmdx/telemetry.rb', line 116 def unsubscribe(event, callable) unless EVENTS.include?(event) raise UnknownEntryError, <<~MSG.chomp unknown telemetry event #{event.inspect}, must be one of #{EVENTS.inspect}. See https://drexed.github.io/cmdx/configuration/#telemetry MSG end if (subscribers = registry[event]) subscribers.delete(callable) registry.delete(event) if subscribers.empty? end self end |