Module: Hooksmith::Instrumentation

Defined in:
lib/hooksmith/instrumentation.rb

Overview

Provides ActiveSupport::Notifications instrumentation for webhook processing.

This module emits events at key points in the webhook lifecycle, enabling metrics collection, tracing, and debugging without modifying core code.

Available Events

  • dispatch.hooksmith - Emitted when a webhook is dispatched

    • payload: { provider:, event:, payload:, processor:, result: }
  • process.hooksmith - Emitted when a processor executes

    • payload: { provider:, event:, processor:, result: }
  • no_processor.hooksmith - Emitted when no processor matches

    • payload: { provider:, event: }
  • multiple_processors.hooksmith - Emitted when multiple processors match

    • payload: { provider:, event:, processor_count: }
  • error.hooksmith - Emitted when an error occurs

    • payload: { provider:, event:, error:, error_class: }

Examples:

Subscribe to all Hooksmith events

ActiveSupport::Notifications.subscribe(/hooksmith/) do |name, start, finish, id, payload|
  duration = finish - start
  Rails.logger.info "#{name} took #{duration}s"
end

Subscribe to specific events

ActiveSupport::Notifications.subscribe('dispatch.hooksmith') do |*args|
  event = ActiveSupport::Notifications::Event.new(*args)
  StatsD.timing('hooksmith.dispatch', event.duration, tags: ["provider:#{event.payload[:provider]}"])
end

Constant Summary collapse

NAMESPACE =
'hooksmith'

Class Method Summary collapse

Class Method Details

.build_subscription_pattern(event_name) ⇒ String, Regexp

Builds the subscription pattern based on the event name type.

Parameters:

  • event_name (String, Regexp, nil)

    the event name or pattern

Returns:

  • (String, Regexp)

    the subscription pattern



101
102
103
104
105
106
107
108
109
110
# File 'lib/hooksmith/instrumentation.rb', line 101

def build_subscription_pattern(event_name)
  case event_name
  when nil
    /\.#{NAMESPACE}$/
  when Regexp
    event_name
  else
    "#{event_name}.#{NAMESPACE}"
  end
end

.instrument(event_name, payload = {}) { ... } ⇒ Object

Instruments a block with the given event name.

Parameters:

  • event_name (String)

    the event name (without namespace)

  • payload (Hash) (defaults to: {})

    the event payload

Yields:

  • the block to instrument

Returns:

  • (Object)

    the result of the block



49
50
51
52
53
54
# File 'lib/hooksmith/instrumentation.rb', line 49

def instrument(event_name, payload = {}, &block)
  return yield unless notifications_available?

  full_name = "#{event_name}.#{NAMESPACE}"
  ActiveSupport::Notifications.instrument(full_name, payload, &block)
end

.notifications_available?Boolean

Checks if ActiveSupport::Notifications is available.

Returns:

  • (Boolean)

    true if available



70
71
72
# File 'lib/hooksmith/instrumentation.rb', line 70

def notifications_available?
  defined?(ActiveSupport::Notifications)
end

.publish(event_name, payload = {}) ⇒ Object

Publishes an event without a block.

Parameters:

  • event_name (String)

    the event name (without namespace)

  • payload (Hash) (defaults to: {})

    the event payload



60
61
62
63
64
65
# File 'lib/hooksmith/instrumentation.rb', line 60

def publish(event_name, payload = {})
  return unless notifications_available?

  full_name = "#{event_name}.#{NAMESPACE}"
  ActiveSupport::Notifications.publish(full_name, payload)
end

.subscribe(event_name = nil) {|name, start, finish, id, payload| ... } ⇒ Object

Subscribes to a Hooksmith event.

Parameters:

  • event_name (String, Regexp, nil) (defaults to: nil)

    the event name, pattern, or nil for all events

Yields:

  • (name, start, finish, id, payload)

    the event callback

Returns:

  • (Object)

    the subscription object



79
80
81
82
83
84
# File 'lib/hooksmith/instrumentation.rb', line 79

def subscribe(event_name = nil, &block)
  return unless notifications_available?

  pattern = build_subscription_pattern(event_name)
  ActiveSupport::Notifications.subscribe(pattern, &block)
end

.unsubscribe(subscriber) ⇒ Object

Unsubscribes from a Hooksmith event.

Parameters:

  • subscriber (Object)

    the subscription object from subscribe



89
90
91
92
93
# File 'lib/hooksmith/instrumentation.rb', line 89

def unsubscribe(subscriber)
  return unless notifications_available?

  ActiveSupport::Notifications.unsubscribe(subscriber)
end