hoodoo 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 21732b5cd34041936e018495404cb3950ff70b85
4
- data.tar.gz: b37d1a9ef5e225653be451d8e775ea07cf5a9690
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MzkyZDI3OGE3NDg2ZDBiODFkZGZlNzhiZGY0YTgzN2FhZDU5OTg4ZA==
5
+ data.tar.gz: !binary |-
6
+ NTQzZGI1NjFhMjU3Y2Y4NTM4MDM0YWJiNGI2MDQyZTQ1NDdmYzIzNQ==
5
7
  SHA512:
6
- metadata.gz: 39c52f8db587f906e2c377ab9fae3939697b872366c07aace735439538f6412fe12efae8996652b746ab31e8704334329e5d71125ca14c60be978f9352aa0308
7
- data.tar.gz: bc4e9624bff7ad092b1ca7e0f86e64c2b8c634ee12649fd22bbb27de26d360dd870dfe4d7644639b5cc30fabbd30294e13c004e9efde77cff07f35fe3879a2eb
8
+ metadata.gz: !binary |-
9
+ ZjA5YzEwZmFlYWNhMjU0YjcyZTAzMTMzODA5MDZiMzk3NDc3ODBlYWViMGRh
10
+ MjQ3MWQ2NTA2NDAxYmUyNzBjYjBhNjIzMzNkMGI2NDZlY2ZlZWU3NDk2MDky
11
+ ZGI0MDVlZmRhZjM4MWI4ZGY4NDNjOTIwODQwOWM3YmYyOTAyNTg=
12
+ data.tar.gz: !binary |-
13
+ MDAyNmY0YzY4MDZiMjY4ZDlkODg3MzRhNzFhNzFjNjEwZjNmZmI3ZDMyM2U3
14
+ N2E4YWU4YTA3OTM4ZjJlYzhiODM3NWRiYzFlYzgxNWYzZjE3OGY1MTIyOGQ2
15
+ ZTRlZGUzOTkxNGM3ZmVjNTA3NTQ2NzljNTMwYmNjNDVjZjI0MDM=
@@ -25,3 +25,6 @@ require 'hoodoo/services'
25
25
  require 'hoodoo/middleware'
26
26
 
27
27
  require 'hoodoo/version'
28
+
29
+ require 'hoodoo/monkey'
30
+
@@ -262,9 +262,13 @@ module Hoodoo
262
262
  @discoverer = if discoverer != nil
263
263
  discoverer
264
264
  elsif @base_uri != nil
265
- Hoodoo::Services::Discovery::ByConvention.new(
266
- :base_uri => @base_uri
267
- )
265
+ if defined?( Hoodoo::Services::Discovery::ByConvention )
266
+ Hoodoo::Services::Discovery::ByConvention.new(
267
+ :base_uri => @base_uri
268
+ )
269
+ else
270
+ raise 'Hoodoo::Client: The constructor parameters indicate the use of a "by convention" discoverer. This discoverer requires ActiveSupport; ensure the ActiveSupport gem is present and "require"-able.'
271
+ end
268
272
  elsif @drb_uri != nil || @drb_port != nil
269
273
  Hoodoo::Services::Discovery::ByDRb.new(
270
274
  :drb_uri => @drb_uri,
@@ -113,6 +113,28 @@ module Hoodoo
113
113
  return do_amqp( d )
114
114
  end
115
115
 
116
+ # Ask Alchemy Flux to send a given HTTP message to a resource.
117
+ #
118
+ # This method is available for Hoodoo monkey patching but must not
119
+ # be called by third party code; it's a private method exposed in
120
+ # the public <tt>monkey_</tt> namespace for patching only. For more,
121
+ # see:
122
+ #
123
+ # * Hoodoo::Monkey
124
+ # * Hoodoo::Monkey::Patch::NewRelicTracedAMQP
125
+ #
126
+ # +http_message+:: Hash describing the message to send.
127
+ # +full_uri+:: Equivalent full URI of the request (information
128
+ # only; the +http_message+ tells Alchemy Flux how
129
+ # to route the message; it does not consult this
130
+ # parameter).
131
+ #
132
+ # The return value is an Alchemy Flux response object.
133
+ #
134
+ def monkey_send_request( http_message, full_uri )
135
+ self.alchemy().send_request_to_resource( http_message )
136
+ end
137
+
116
138
  private
117
139
 
118
140
  # Call Alchemy to make an HTTP simulated request over AMQP to a
@@ -164,7 +186,7 @@ module Hoodoo
164
186
  http_message[ 'session_id' ] = self.session_id()
165
187
  end
166
188
 
167
- amqp_response = self.alchemy().send_request_to_resource( http_message )
189
+ amqp_response = monkey_send_request( http_message, data.full_uri )
168
190
 
169
191
  description_of_response = DescriptionOfResponse.new
170
192
  description_of_response.action = action
@@ -193,6 +215,7 @@ module Hoodoo
193
215
  end
194
216
 
195
217
  end
218
+
196
219
  end
197
220
  end
198
221
  end
@@ -0,0 +1,13 @@
1
+ ########################################################################
2
+ # File:: monkey.rb
3
+ # (C):: Loyalty New Zealand 2016
4
+ #
5
+ # Purpose:: Require the Hoodoo monkey patching engine and any built-in
6
+ # patches, which will enable themselves (or not) according to
7
+ # their individual RDoc-documented descriptions.
8
+ # ----------------------------------------------------------------------
9
+ # 12-Apr-2016 (ADH): Created.
10
+ ########################################################################
11
+
12
+ require 'hoodoo/monkey/monkey'
13
+ require 'hoodoo/monkey/patch/newrelic_traced_amqp'
@@ -0,0 +1,308 @@
1
+ ########################################################################
2
+ # File:: monkey.rb
3
+ # (C):: Loyalty New Zealand 2016
4
+ #
5
+ # Purpose:: Official, reversible monkey patching.
6
+ # ----------------------------------------------------------------------
7
+ # 11-Apr-2016 (ADH): Created.
8
+ ########################################################################
9
+
10
+ module Hoodoo
11
+
12
+ # Hoodoo provides monkey patching hook points as first class citizens and
13
+ # includes a registration, enabling and disabling mechanism through the
14
+ # Hoodoo::Monkey class.
15
+ #
16
+ # You encapsulate monkey patch code inside a module. This module will be
17
+ # used to patch one or more target other classes or modules. Usually, one
18
+ # module will only be used to patch one other kind of class or module;
19
+ # re-use of a patch module usually only makes sense when patching one
20
+ # or more subclasses from a common ancestor where some, but not all of
21
+ # the subclass types are to be patched (if you wanted to patch all of them
22
+ # you'd just patch the base class).
23
+ #
24
+ # Inside your module, you write one or two sub-modules. One of these
25
+ # patches instance methods in the target, the other patches class methods.
26
+ # The mechanism used to patch instance or class methods is different in
27
+ # Ruby, thus the distinct module use; it also helps keep your code clear
28
+ # of distracting syntax and make it very obvious what kind of "thing" is
29
+ # being replaced.
30
+ #
31
+ # Monkey patch methods are sent to the patch target using `prepend`, the
32
+ # Ruby 2 mechanism which means the original overriden implementation can
33
+ # be called via +super+, just as if you were writing a subclass.
34
+ #
35
+ # For examples, see method Hoodoo::Monkey::register.
36
+ #
37
+ # Any public method in the API can be patched, since the public API is by
38
+ # definition public and stable. Sometimes, normally-private methods are
39
+ # exposed for monkey patching as public methods with the name prefix of
40
+ # "<tt>monkey_</tt>" - such methods are *NOT* intended to be called by
41
+ # client code in general, but can be patched. It is only completely safe to
42
+ # to patch a method in a wrapper fashion, e.g. to filter inputs or outputs;
43
+ # thus whenever possible, always call +super+ at some point within your
44
+ # replacement implementation. If you completely replace an implementation
45
+ # with a custom version, you risk your code breaking even with patch level
46
+ # changes to Hoodoo, since only the public _interface_ is guaranteed; the
47
+ # way in which it is _implemented_ is not.
48
+ #
49
+ # You tell the monkey patching system about the outer container module, the
50
+ # instance and/or class patch modules and the target entity via a call to
51
+ # Hoodoo::Monkey::register. See this for more details. Use
52
+ # Hoodoo::Monkey::enable to actually 'switch on' the patch and
53
+ # Hoodoo::Monkey::disable to 'switch off' the patch again.
54
+ #
55
+ # The patch engine is "require'd" by Hoodoo as the very last thing in all of
56
+ # its other inclusion steps when 'hoodoo.rb' ("everything") is included by
57
+ # code. If individual sub-modules of Hoodoo are included by client code, it
58
+ # will be up to them when (and if) the monkey patch engine is brought in.
59
+ #
60
+ # Hoodoo authors should note namespaces Hoodoo::Monkey::Patch and
61
+ # Hoodoo::Monkey::Chaos inside which out-of-the-box Hoodoo patch code should
62
+ # be defined. Third party patches must use their own namespaces to avoid any
63
+ # potential for collision with future new Hoodoo patch modules.
64
+ #
65
+ module Monkey
66
+ @@modules = {}
67
+
68
+ # Register a set of monkey patch modules with Hoodoo::Monkey - see the
69
+ # top-level Hoodoo::Monkey documentation for an introduction and some
70
+ # high level guidelines for monkey patch code.
71
+ #
72
+ # _Named_ parameters are:
73
+ #
74
+ # +target_unit+:: The Class or Module to be patched.
75
+ # +extension_module+:: The module that identifies the collection of
76
+ # instance and/or class methods to overwrite
77
+ # inside the targeted unit. This MUST define
78
+ # a nested module called "InstanceExtensions"
79
+ # containing method definitions that will
80
+ # override same-name instance methods in the
81
+ # targeted unit, or a nested module called
82
+ # "ClassExtensions" to override class methods,
83
+ # or both.
84
+ #
85
+ # For example, suppose we have this class:
86
+ #
87
+ # class Foo
88
+ # def bar
89
+ # 2 * 2
90
+ # end
91
+ #
92
+ # def self.bar
93
+ # 3 * 3
94
+ # end
95
+ # end
96
+ #
97
+ # Foo.new.bar
98
+ # # => 4
99
+ # Foo.bar
100
+ # # => 9
101
+ #
102
+ # Next define modules which extend/override methods in the above class:
103
+ #
104
+ # module ExtendedFoo
105
+ # module InstanceExtensions
106
+ # def bar
107
+ # 5 * 5
108
+ # end
109
+ # end
110
+ #
111
+ # module ClassExtensions
112
+ #
113
+ # # Even though this module will be used to override class methods
114
+ # # in the target, we define the module methods with "def bar", not
115
+ # # "def self.bar".
116
+ # #
117
+ # def bar
118
+ # 7 * 7
119
+ # end
120
+ # end
121
+ # end
122
+ #
123
+ # At this point, the extension is defined, but not registered with Hoodoo
124
+ # and not yet enabled. Register it with:
125
+ #
126
+ # Hoodoo::Monkey.register(
127
+ # target_unit: Foo,
128
+ # extension_module: ExtendedFoo
129
+ # )
130
+ #
131
+ # The code is now registered so that it can be easily enabled or disabled
132
+ # via the given +extension_module+ value:
133
+ #
134
+ # Hoodoo::Monkey.enable( ExtendedFoo )
135
+ #
136
+ # Foo.new.bar
137
+ # # => 25
138
+ # Foo.bar
139
+ # # => 49
140
+ #
141
+ # Hoodoo::Monkey.disable( ExtendedFoo )
142
+ #
143
+ # Foo.new.bar
144
+ # # => 4
145
+ # Foo.bar
146
+ # # => 9
147
+ #
148
+ # You can register the same extension modules for multiple target units,
149
+ # but it can only be enabled or disabled all in one go for all targets.
150
+ #
151
+ def self.register( target_unit:, extension_module: )
152
+
153
+ if extension_module.const_defined?( 'InstanceExtensions', false )
154
+ instance_methods_module = extension_module.const_get( 'InstanceExtensions' )
155
+ end
156
+
157
+ if extension_module.const_defined?( 'ClassExtensions', false )
158
+ class_methods_module = extension_module.const_get( 'ClassExtensions' )
159
+ end
160
+
161
+ if instance_methods_module.nil? && class_methods_module.nil?
162
+ raise "Hoodoo::Monkey::register: You must define either an InstanceExtensions module ClassExtensions module or both inside '#{ extension_module.inspect }'"
163
+ end
164
+
165
+ @@modules[ extension_module ] ||= {}
166
+ @@modules[ extension_module ][ target_unit ] =
167
+ [
168
+ {
169
+ :patch_module => instance_methods_module,
170
+ :patch_target => target_unit
171
+ },
172
+ {
173
+ :patch_module => class_methods_module,
174
+ :patch_target => target_unit.singleton_class
175
+ }
176
+ ]
177
+
178
+ end
179
+
180
+ # Enable a given monkey patch, using the extension module parameter value
181
+ # given to a prior call to ::register (see there for more information).
182
+ #
183
+ # The initial patch installation is done via <tt>Module#prepend</tt>, so
184
+ # you are able to call +super+ to invoke the original implementation from
185
+ # the overriding implementation, as if you were writing a subclass.
186
+ #
187
+ # Instance and class method monkey patches should try very hard to always
188
+ # call "super" so that an overridden/patched public API method will still
189
+ # call back to its original implementation; the wrapper just filters
190
+ # inputs and outputs or adds additional behaviour. This way, changes to
191
+ # the Hoodoo implementation will not break the patch.
192
+ #
193
+ # Patching is global; it is not lexically scoped. Use Ruby refinements
194
+ # manually if you want lexically scoped patches.
195
+ #
196
+ # _Named_ parameters are:
197
+ #
198
+ # +extension_module+:: A module previously passed in the same-named
199
+ # parameter to ::register. The instance and/or class
200
+ # methods defined therein will be applied to the
201
+ # previously registered target.
202
+ #
203
+ # Enabling the same extension multiple times has no side effects.
204
+ #
205
+ def self.enable( extension_module: )
206
+ if ( target_units_hash = @@modules[ extension_module ] ).nil?
207
+ raise "Hoodoo::Monkey::enable: Extension module '#{ extension_module.inspect }' is not registered"
208
+ end
209
+
210
+ target_units_hash.each_value do | target_and_module_array |
211
+ target_and_module_array.each do | target_and_module_array_entry |
212
+ patch_module = target_and_module_array_entry[ :patch_module ]
213
+ patch_target = target_and_module_array_entry[ :patch_target ]
214
+
215
+ next if patch_module.nil?
216
+
217
+ # If the patch contains a target-based collection of unbound
218
+ # methods, it was disabled previously (see the 'disable' code).
219
+ # Re-enable by re-building the module's methods.
220
+ #
221
+ if target_and_module_array_entry.has_key?( :unbound_methods )
222
+
223
+ target_and_module_array_entry[ :unbound_methods ].each do | method_name, unbound_method |
224
+ patch_module.send( :define_method, method_name, unbound_method )
225
+ end
226
+
227
+ # Discard the references to the now-unneeded unbound methods.
228
+ #
229
+ target_and_module_array_entry.delete( :unbound_methods )
230
+
231
+ end
232
+
233
+ # *Always* call "prepend". If the same patch modules are being used
234
+ # against multiple targets, the fact that the code above saw that a
235
+ # module had been disabled for one particular target doesn't mean
236
+ # that the module had previously been inserted into the ancestors
237
+ # for "this" target. It might have been registered later.
238
+ #
239
+ # This is safe as repeat calls do nothing; they don't even reorder
240
+ # the ancestor chain.
241
+ #
242
+ patch_target.prepend( patch_module )
243
+
244
+ end
245
+ end
246
+ end
247
+
248
+ # Disable a patch previously enabled with ::enable (see there for more
249
+ # information).
250
+ #
251
+ # A disabled patch will still be present in a target unit's +ancestors+
252
+ # list, but has no performance impact. Repeated enable/disable cycles
253
+ # incur no additional runtime performance penalties.
254
+ #
255
+ # _Named_ parameters are:
256
+ #
257
+ # +extension_module+:: A module previously passed in the same-named
258
+ # parameter to ::register. The instance and/or class
259
+ # methods defined therein will be removed from the
260
+ # previously registered target.
261
+ #
262
+ # Disabling the same extension multiple times has no side effects.
263
+ #
264
+ def self.disable( target_unit: nil, extension_module: )
265
+ if ( target_units_hash = @@modules[ extension_module ] ).nil?
266
+ raise "Hoodoo::Monkey::disable: Extension module '#{ extension_module.inspect }' is not registered"
267
+ end
268
+
269
+ target_units_hash.each_value do | target_and_module_array |
270
+ target_and_module_array.each do | target_and_module_array_entry |
271
+ patch_module = target_and_module_array_entry[ :patch_module ]
272
+ patch_target = target_and_module_array_entry[ :patch_target ]
273
+
274
+ next if patch_module.nil? || target_and_module_array_entry.has_key?( :unbound_methods )
275
+
276
+ target_and_module_array_entry[ :unbound_methods ] = {}
277
+
278
+ # We take unbound method references to every patch module method,
279
+ # then remove the originals. In the re-enable code, the methods
280
+ # are redefined in the module. This approach means that any
281
+ # target unit with the module in its ancestors chain will see the
282
+ # change immediately. We don't need to iterate over them.
283
+ #
284
+ patch_module.instance_methods( false ).each do | method_name |
285
+ unbound_method = patch_module.instance_method( method_name )
286
+ target_and_module_array_entry[ :unbound_methods ][ method_name ] = unbound_method
287
+ patch_module.send( :remove_method, method_name )
288
+ end
289
+ end
290
+ end
291
+ end
292
+
293
+ # Out-of-the-box regular monkey patches (versus chaos monkeys) for Hoodoo.
294
+ # These typically predictably extend or modify existing Hoodoo behaviour.
295
+ # See Hoodoo::Monkey for details.
296
+ #
297
+ module Patch
298
+ end
299
+
300
+ # Out-of-the-box chaos monkey patches (versus regular monkeys) for Hoodoo.
301
+ # These typically provoke unpredictable states inside existing Hoodoo
302
+ # behaviour to exercise "unhappy path" code paths. See Hoodoo::Monkey for
303
+ # details.
304
+ #
305
+ module Chaos
306
+ end
307
+ end
308
+ end
@@ -0,0 +1,195 @@
1
+ ########################################################################
2
+ # File:: newrelic_traced_amqp.rb
3
+ # (C):: Loyalty New Zealand 2015
4
+ #
5
+ # Purpose:: Extend the AMQP endpoint to support NewRelic cross-app
6
+ # transaction tracing. Only defined and registered if the
7
+ # NewRelic gem is available and Hoodooo Client is in scope.
8
+ #
9
+ # See Hoodoo::Monkey::Patch::NewRelicTracedAMQP for more.
10
+ # ----------------------------------------------------------------------
11
+ # 08-Apr-2016 (RJS): Created.
12
+ ########################################################################
13
+
14
+ module Hoodoo
15
+ module Monkey
16
+ module Patch
17
+
18
+ begin
19
+ require 'newrelic_rpm' # Raises LoadError if NewRelic is absent
20
+
21
+ # Wrap Hoodoo::Client::Endpoint::AMQP using NewRelic transaction
22
+ # tracing so that over-queue inter-resource calls get connected
23
+ # together in NewRelic's view of the world.
24
+ #
25
+ # This module self-registers with Hooodoo::Monkey and, provided
26
+ # that Hoodoo::Services::Middleware is defined at parse-time and
27
+ # Hoodoo::Services::Middleware.environment.production? reports
28
+ # +false+, will be enabled by default.
29
+ #
30
+ module NewRelicTracedAMQP
31
+
32
+ # Instance methods to patch over Hoodoo::Client::Endpoint::AMQP.
33
+ #
34
+ module InstanceExtensions
35
+
36
+ # Wrap the request with NewRelic's cross-app transaction tracing.
37
+ # This adds headers to the request and extracts header data from
38
+ # the response. It calls the original implementation via +super+.
39
+ #
40
+ # +http_message+:: Hash describing the message to send.
41
+ #
42
+ # +full_uri+:: URI being sent to. This is somewhat meaningless
43
+ # when using AMQP but NewRelic requires it.
44
+ #
45
+ def monkey_send_request( http_message, full_uri )
46
+ amqp_response = nil
47
+ newrelic_request = ::Hoodoo::Monkey::Patch::NewRelicTracedAMQP::AMQPNewRelicRequestWrapper.new(
48
+ http_message,
49
+ full_uri
50
+ )
51
+
52
+ ::NewRelic::Agent::CrossAppTracing.tl_trace_http_request( newrelic_request ) do
53
+
54
+ # Disable further tracing in request to avoid double counting
55
+ # if connection wasn't started (which calls request again).
56
+ #
57
+ ::NewRelic::Agent.disable_all_tracing do
58
+
59
+ amqp_response = super( http_message, full_uri )
60
+
61
+ # The outer block extracts required information from the
62
+ # object returned by this block. Need to wrap it match the
63
+ # expected interface.
64
+ #
65
+ ::Hoodoo::Monkey::Patch::NewRelicTracedAMQP::AMQPNewRelicResponseWrapper.new(
66
+ amqp_response
67
+ )
68
+
69
+ end
70
+ end
71
+
72
+ return amqp_response
73
+ end
74
+ end
75
+
76
+ # Wrapper class for an AMQP request which conforms to the API that
77
+ # NewRelic expects.
78
+ #
79
+ class AMQPNewRelicRequestWrapper
80
+
81
+ # Wrap the Alchemy Flux +http_message+ aimed at the specified
82
+ # +full_uri+.
83
+ #
84
+ # +http_message+:: Hash describing the request for Alchemy Flux.
85
+ # +full_uri+:: Full target URI, as a String.
86
+ #
87
+ def initialize( http_message, full_uri )
88
+ @http_message = http_message
89
+ @full_uri = full_uri
90
+ end
91
+
92
+ # String describing what kind of request this is.
93
+ #
94
+ def type
95
+ self.class.to_s()
96
+ end
97
+
98
+ # String describing this request's intended host.
99
+ #
100
+ def host
101
+ @http_message[ 'host' ]
102
+ end
103
+
104
+ # String describing this request's HTTP verb (GET, POST and
105
+ # so-on). String case is undefined, so perform case-insensitive
106
+ # comparisions.
107
+ #
108
+ def method
109
+ @http_message[ 'verb' ]
110
+ end
111
+
112
+ # Key lookup is delegated to the headers Hash per NewRelic's
113
+ # expectations of how a request behaves.
114
+ #
115
+ # +key+:: Hash key to look up.
116
+ #
117
+ def []( key )
118
+ @http_message[ 'headers' ][ key ]
119
+ end
120
+
121
+ # Key setting is delegated to the headers Hash per NewRelic's
122
+ # expectations of how a request behaves.
123
+ #
124
+ # +key+:: Key of Hash entry to modify.
125
+ # +value+:: New or replacement value for identified Hash entry.
126
+ #
127
+ def []=( key, value )
128
+ @http_message[ 'headers' ][ key ] = value
129
+ end
130
+
131
+ # String describing the full request URI.
132
+ #
133
+ def uri
134
+ @full_uri
135
+ end
136
+
137
+ end
138
+
139
+ # Wrapper class for an AMQP request which conforms to the API that
140
+ # NewRelic expects.
141
+ #
142
+ class AMQPNewRelicResponseWrapper
143
+
144
+ # The +response_hash+ to be wrapped.
145
+ #
146
+ # +response_hash+:: Hash describing the response returned from
147
+ # Alchemy Flux.
148
+ #
149
+ def initialize( response_hash )
150
+ @response_hash = response_hash
151
+ end
152
+
153
+ # If the NewRelic cross-app tracing header is the +key+, return the
154
+ # value of the header that matches that key. Otherwise look up the
155
+ # key like normal.
156
+ #
157
+ # +key+:: Hash key to look up.
158
+ #
159
+ def []( key )
160
+ if key == ::NewRelic::Agent::CrossAppTracing::NR_APPDATA_HEADER
161
+ @response_hash[ 'headers' ][ key ]
162
+ else
163
+ @response_hash[ key ]
164
+ end
165
+ end
166
+ end
167
+ end
168
+
169
+ # Register this class with the Hoodoo monkey patch engine in any
170
+ # non-production environment.
171
+ #
172
+ if defined?( Hoodoo::Client ) &&
173
+ defined?( Hoodoo::Client::Endpoint ) &&
174
+ defined?( Hoodoo::Client::Endpoint::AMQP )
175
+
176
+ Hoodoo::Monkey.register(
177
+ target_unit: Hoodoo::Client::Endpoint::AMQP,
178
+ extension_module: Hoodoo::Monkey::Patch::NewRelicTracedAMQP
179
+ )
180
+
181
+ if defined?( Hoodoo::Services ) &&
182
+ defined?( Hoodoo::Services::Middleware) &&
183
+ Hoodoo::Services::Middleware.environment.production? != true
184
+
185
+ Hoodoo::Monkey.enable( extension_module: Hoodoo::Monkey::Patch::NewRelicTracedAMQP )
186
+ end
187
+ end
188
+
189
+ rescue LoadError
190
+ # No NewRelic => do nothing
191
+ end
192
+
193
+ end # module Patch
194
+ end # module Monkey
195
+ end # module Hoodoo