class CacheQL::FieldInstrumentation

Constants

NAME

Public Class Methods

log(&block) click to toggle source

For use in an around_action call to log all fields. For example:

around_action :log_field_instrumentation

def log_field_instrumentation(&block)

CacheQL::FieldInstrumentation.log(&block)

end

# File lib/cacheql/field_instrumentation.rb, line 15
def self.log(&block)
  field_instruments = Hash.new(0)
  ActiveSupport::Notifications.subscribe(NAME) do |*args|
    event = ActiveSupport::Notifications::Event.new(*args)
    field_instruments[event.payload[:label]] += event.duration
  end

  block.call

  ActiveSupport::Notifications.unsubscribe(NAME)
  field_instruments.sort_by(&:last).reverse.each do |field, ms|
    CacheQL::Railtie.config.logger.info "[CacheQL::Tracing] #{field} took #{ms.round(3)}ms"
  end
end
new(instrumenter) click to toggle source

instrumenter must respond to instrument See ScoutApm::Tracer for example

# File lib/cacheql/field_instrumentation.rb, line 32
def initialize(instrumenter)
  @instrumenter = instrumenter
end

Public Instance Methods

instrument(type, field) click to toggle source

Track timing for all fields

# File lib/cacheql/field_instrumentation.rb, line 37
def instrument(type, field)
  # Ignore internal GraphQL types
  if type.name.starts_with?("__")
    field
  else
    label = "#{type.name}.#{field.name}"
    old_resolve_proc = field.resolve_proc

    new_resolve_proc = -> (obj, args, ctx) {
      ActiveSupport::Notifications.instrument(NAME, label: label) do
        @instrumenter.instrument("GraphQL", label) do
          resolved = old_resolve_proc.call(obj, args, ctx)
          resolved
        end
      end
    }

    # Return a copy of `field`, with a new resolve proc
    field.redefine do
      resolve(new_resolve_proc)
    end
  end
end