Module: HTTPInstrumentation::Instrumentation

Defined in:
lib/http_instrumentation/instrumentation.rb,
lib/http_instrumentation/instrumentation/curb_hook.rb,
lib/http_instrumentation/instrumentation/http_hook.rb,
lib/http_instrumentation/instrumentation/ethon_hook.rb,
lib/http_instrumentation/instrumentation/excon_hook.rb,
lib/http_instrumentation/instrumentation/httpx_hook.rb,
lib/http_instrumentation/instrumentation/patron_hook.rb,
lib/http_instrumentation/instrumentation/net_http_hook.rb,
lib/http_instrumentation/instrumentation/typhoeus_hook.rb,
lib/http_instrumentation/instrumentation/httpclient_hook.rb

Defined Under Namespace

Modules: CurbHook, EthonHook, ExconHook, HTTPClientHook, HTTPHook, HTTPXHook, NetHTTPHook, PatronHook, TyphoeusHook

Class Method Summary collapse

Class Method Details

.instrument!(klass, instrumentation_module, methods) ⇒ Object

Helper method to add an instrumentation module to methods on a class. The methods must be defined in the instrumentation module.

If the methods have already been prepended on the class, then module will be prepended to the class. Otherwise, the methods will be aliased and the module will be included in the class. This is because prepending and aliasing methods are not compatible with each other and other instrumentation libraries may have already prepended the methods. Aliasing is the default strategy because prepending after aliasing will work, but aliasing after prepending will not.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/http_instrumentation/instrumentation.rb', line 31

def instrument!(klass, instrumentation_module, methods)
  INSTRUMENT_LOCK.synchronize do
    return if klass.include?(instrumentation_module)

    methods = Array(methods).collect(&:to_sym)

    if HTTPInstrumentation.force_prepend? || methods_defined_in_module?(klass, methods)
      klass.prepend(instrumentation_module)
      instrumentation_module.aliased = false
    else
      methods.each do |method|
        instrumentation_module.alias_method("#{method}_with_http_instrumentation", method)
      end

      klass.include(instrumentation_module)

      swap_methods = methods.reject { |method| defines_method?(klass, "#{method}_without_http_instrumentation") }

      swap_methods.each do |method|
        klass.alias_method("#{method}_without_http_instrumentation", method)
      end

      # The aliased flag must be set before the instrumented methods are
      # swapped in; a call landing in between would take the super branch
      # and raise NoMethodError since the module was included, not prepended.
      instrumentation_module.aliased = true

      swap_methods.each do |method|
        klass.alias_method(method, "#{method}_with_http_instrumentation")
      end
    end
  end
end