Class: CMDx::Telemetry

Inherits:
Object
  • Object
show all
Defined in:
lib/cmdx/telemetry.rb

Overview

Pub/sub for runtime lifecycle events (see EVENTS). Subscribers are callables receiving an Event data object. Runtime emits events only when subscribers are registered so telemetry has zero cost when unused.

Defined Under Namespace

Classes: Event

Constant Summary collapse

EVENTS =

Lifecycle event names Runtime emits.

%i[
  task_started
  task_deprecated
  task_retried
  task_rolled_back
  task_executed
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTelemetry

Returns a new instance of Telemetry.



37
38
39
# File 'lib/cmdx/telemetry.rb', line 37

def initialize
  @registry = {}
end

Instance Attribute Details

#registryObject (readonly)

Returns the value of attribute registry.



35
36
37
# File 'lib/cmdx/telemetry.rb', line 35

def registry
  @registry
end

Instance Method Details

#countInteger

Returns total subscribers across all events.

Returns:

  • (Integer)

    total subscribers across all events



129
130
131
# File 'lib/cmdx/telemetry.rb', line 129

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.

Parameters:

  • event (Symbol)
  • payload (Event)


139
140
141
142
143
144
145
146
# File 'lib/cmdx/telemetry.rb', line 139

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

Returns:

  • (Boolean)


119
120
121
# File 'lib/cmdx/telemetry.rb', line 119

def empty?
  registry.empty?
end

#initialize_copy(source) ⇒ void

This method returns an undefined value.

Parameters:

  • source (Telemetry)

    registry to duplicate



43
44
45
# File 'lib/cmdx/telemetry.rb', line 43

def initialize_copy(source)
  @registry = source.registry.transform_values(&:dup)
end

#lookup(event) ⇒ #call

Parameters:

  • event (Symbol)

Returns:

  • (#call)

Raises:



109
110
111
112
113
114
115
116
# File 'lib/cmdx/telemetry.rb', line 109

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

#sizeInteger

Returns number of subscribed events.

Returns:

  • (Integer)

    number of subscribed events



124
125
126
# File 'lib/cmdx/telemetry.rb', line 124

def size
  registry.size
end

#subscribe(event, callable = nil, &block) {|evt| ... } ⇒ Telemetry

Registers a subscriber for ‘event`.

Parameters:

  • event (Symbol)

    one of EVENTS

  • callable (#call, nil) (defaults to: nil)

    subscriber callable; pass either this or a block

  • block (#call, nil)

    subscriber when ‘callable` is omitted

Yield Parameters:

Returns:

Raises:

  • (ArgumentError)

    when both ‘callable` and a block are provided, when the subscriber isn’t callable, or when ‘event` is unknown



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/cmdx/telemetry.rb', line 56

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`.

Parameters:

  • event (Symbol)

Returns:

  • (Boolean)

    true when at least one subscriber exists for ‘event`



102
103
104
# File 'lib/cmdx/telemetry.rb', line 102

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.

Parameters:

  • event (Symbol)

    one of EVENTS

  • callable (#call)

    the subscriber to remove

Returns:

Raises:



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/cmdx/telemetry.rb', line 84

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