Sha256: 37dd75b390efbefc869ac49d6c61aade5e395d53ef7d4eeb0030d4c93647c3ce

Contents?: true

Size: 1.44 KB

Versions: 2

Compression:

Stored size: 1.44 KB

Contents

# frozen_string_literal: true

require_relative './instrumentors/all'

module InstrumentAllTheThings
  class MethodInstrumentor
    WRAPPERS = {
      # Note that the order of these hash keys are applied top to bottom, with the first inserted key
      # being the inner most wrapper
      gc_stats: Instrumentors::GC_STATS_WRAPPER,
      error_logging: Instrumentors::ERROR_LOGGING_WRAPPER,
      execution_counts_and_timing: Instrumentors::EXECUTION_COUNT_AND_TIMING_WRAPPER,
      trace: Instrumentors::TRACE_WRAPPER,
    }.freeze

    DEFAULT_OPTIONS = {
      trace: true,
      gc_stats: false,
      error_logging: true,
      execution_counts_and_timing: false,
    }.freeze

    attr_accessor :options, :instrumentor

    def initialize(options)
      self.options = DEFAULT_OPTIONS.merge(options)

      build_instrumentor

      freeze
    end

    def build_instrumentor
      procs = WRAPPERS.collect do |type, builder|
        next unless options[type]

        builder.call(options[type], options[:context])
      end.compact

      self.instrumentor = combine_procs(procs)
    end

    def invoke(klass:, &blk)
      instrumentor.call(klass, blk)
    end

    private

    def combine_procs(procs)
      # I know it's crazy, but this wraps procs which take "Next Block"
      # and "Final Block"
      procs.inject(->(_, f) { f.call }) do |next_blk, current_blk|
        proc { |k, final| current_blk.call(k, next_blk, final) }
      end
    end
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
instrument_all_the_things-1.4.0 lib/instrument_all_the_things/method_instrumentor.rb
instrument_all_the_things-4.0.0 lib/instrument_all_the_things/method_instrumentor.rb