Module: LittleGhost::Events

Defined in:
lib/little_ghost/events.rb

Overview

Events lets an application react to noteworthy agent activity without coupling LittleGhost to a logger or event backend. Listeners can feed local diagnostics, alerts, or an application's own event pipeline.

class WarningCollector
attr_reader :events

def initialize
  @events = []
end

def emit(event)
  events << event
end
end

warnings = WarningCollector.new
LittleGhost::Events.subscribe(warnings) do |event|
%i[warn error].include?(event[:level])
end
LittleGhost::Events.warn("support.case.stalled", case_id: "case-42")
warnings.events.last[:name] # => "support.case.stalled"

Events describe point-in-time facts. Instrumentation measures work that has a start and finish. Payloads are copied, limited to JSON-safe values, and delivered with context local to the current execution. A broken listener never breaks the operation that emitted the event.

Defined Under Namespace

Classes: ConsoleListener, Reporter

Constant Summary collapse

LEVELS =

Severity levels accepted by .emit and its convenience methods.

%i[debug info warn error].freeze

Class Method Summary collapse

Class Method Details

.console_outputObject

The process-wide JSON-line console destination, or nil when console delivery is disabled.



207
208
209
# File 'lib/little_ghost/events.rb', line 207

def console_output
  reporter_mutex.synchronize { @console_output }
end

.console_output=(destination) ⇒ Object

Selects :stdout, :stderr, or nil as the process-wide JSON-line console destination. Replacing the destination leaves other listeners unchanged.



214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/little_ghost/events.rb', line 214

def console_output=(destination)
  unless [nil, :stdout, :stderr].include?(destination)
    raise ArgumentError, "event log destination must be :stdout, :stderr, or nil"
  end

  reporter_mutex.synchronize do
    @reporter ||= Reporter.new
    @reporter.unsubscribe(@console_listener) if @console_listener
    @console_output = destination
    @console_listener = destination && ConsoleListener.new(io: (destination == :stdout) ? $stdout : $stderr)
    @reporter.subscribe(@console_listener) if @console_listener
  end
end

.contextObject

Copies the current event context.



235
# File 'lib/little_ghost/events.rb', line 235

def context = reporter.context

.reporterObject

Accesses the process-wide reporter.



190
191
192
# File 'lib/little_ghost/events.rb', line 190

def reporter
  reporter_mutex.synchronize { @reporter ||= Reporter.new }
end

.reporter=(value) ⇒ Object

Replaces the process-wide reporter. Existing references are unaffected.

Raises:

  • (ArgumentError)


195
196
197
198
199
200
201
202
203
# File 'lib/little_ghost/events.rb', line 195

def reporter=(value)
  raise ArgumentError, "reporter must be an event reporter" unless value.is_a?(Reporter)

  reporter_mutex.synchronize do
    @reporter&.unsubscribe(@console_listener) if @console_listener
    @reporter = value
    @reporter.subscribe(@console_listener) if @console_listener
  end
end

.subscribeObject

Subscribes a process-wide listener.



229
230
# File 'lib/little_ghost/events.rb', line 229

def subscribe(...) = reporter.subscribe(...)
# Unsubscribes a process-wide listener.

.subscribed(listener, &block) ⇒ Object

Subscribes listener only while the block runs.

Raises:

  • (ArgumentError)


249
250
251
252
253
254
255
# File 'lib/little_ghost/events.rb', line 249

def subscribed(listener, &block)
  raise ArgumentError, "event listener must respond to emit" unless listener.respond_to?(:emit)

  listeners = ExecutionState[:little_ghost_event_listeners] || []
  entry = {listener:, filter: nil}
  ExecutionState.with(little_ghost_event_listeners: listeners + [entry], &block)
end

.unsubscribeObject

Unsubscribes a process-wide listener.



231
232
# File 'lib/little_ghost/events.rb', line 231

def unsubscribe(...) = reporter.unsubscribe(...)
# Adds event context while a block runs.

.with_contextObject

Adds event context while a block runs.



233
234
# File 'lib/little_ghost/events.rb', line 233

def with_context(...) = reporter.with_context(...)
# Copies the current event context.