Module: Easyop::Plugins::Instrumentation

Defined in:
lib/easyop/plugins/instrumentation.rb

Overview

Instruments every operation call via ActiveSupport::Notifications.

Install on ApplicationOperation (propagates to all subclasses):

class ApplicationOperation
  include Easyop::Operation
  plugin Easyop::Plugins::Instrumentation
end

Event: “easyop.operation.call” Payload keys:

:operation  — String class name, e.g. "Users::Register"
:success    — Boolean
:error      — String | nil  (ctx.error on failure)
:duration   — Float ms
:ctx        — The Easyop::Ctx object (read-only reference)

Subscribe manually:

ActiveSupport::Notifications.subscribe("easyop.operation.call") do |event|
  Rails.logger.info "[EasyOp] #{event.payload[:operation]}#{event.payload[:success] ? 'ok' : 'FAILED'}"
end

Or use the built-in log subscriber:

Easyop::Plugins::Instrumentation.attach_log_subscriber

Defined Under Namespace

Modules: RunWrapper

Constant Summary collapse

EVENT =
"easyop.operation.call"

Class Method Summary collapse

Class Method Details

.attach_log_subscriberObject

Attach a default subscriber that logs to Rails.logger (or stdout). Call once in an initializer: Easyop::Plugins::Instrumentation.attach_log_subscriber



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/easyop/plugins/instrumentation.rb', line 38

def self.attach_log_subscriber
  ActiveSupport::Notifications.subscribe(EVENT) do |*args|
    event = ActiveSupport::Notifications::Event.new(*args)
    p     = event.payload
    next if p[:operation].nil?

    status = p[:success] ? "ok" : "FAILED"
    ms     = event.duration.round(1)
    line   = "[EasyOp] #{p[:operation]} #{status} (#{ms}ms)"
    line  += "#{p[:error]}" if p[:error]

    logger = defined?(Rails) && Rails.respond_to?(:logger) ? Rails.logger : Logger.new($stdout)
    if p[:success]
      logger.info line
    else
      logger.warn line
    end
  end
end

.install(base, **_options) ⇒ Object



32
33
34
# File 'lib/easyop/plugins/instrumentation.rb', line 32

def self.install(base, **_options)
  base.prepend(RunWrapper)
end