hoodoo 1.7.0 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
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