newrelic_rpm 6.15.0 → 7.0.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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +96 -22
  3. data/README.md +2 -2
  4. data/lib/new_relic/agent.rb +0 -6
  5. data/lib/new_relic/agent/autostart.rb +1 -2
  6. data/lib/new_relic/agent/configuration/default_source.rb +270 -104
  7. data/lib/new_relic/agent/configuration/manager.rb +2 -2
  8. data/lib/new_relic/agent/datastores/redis.rb +0 -4
  9. data/lib/new_relic/agent/distributed_tracing.rb +0 -66
  10. data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +0 -16
  11. data/lib/new_relic/agent/instrumentation/bunny.rb +10 -152
  12. data/lib/new_relic/agent/instrumentation/bunny/chain.rb +45 -0
  13. data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +152 -0
  14. data/lib/new_relic/agent/instrumentation/bunny/prepend.rb +35 -0
  15. data/lib/new_relic/agent/instrumentation/curb.rb +9 -241
  16. data/lib/new_relic/agent/instrumentation/curb/chain.rb +93 -0
  17. data/lib/new_relic/agent/instrumentation/curb/instrumentation.rb +222 -0
  18. data/lib/new_relic/agent/instrumentation/curb/prepend.rb +63 -0
  19. data/lib/new_relic/agent/instrumentation/delayed_job/chain.rb +38 -0
  20. data/lib/new_relic/agent/instrumentation/delayed_job/instrumentation.rb +53 -0
  21. data/lib/new_relic/agent/instrumentation/delayed_job/prepend.rb +34 -0
  22. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +8 -50
  23. data/lib/new_relic/agent/instrumentation/excon.rb +2 -1
  24. data/lib/new_relic/agent/instrumentation/grape.rb +13 -113
  25. data/lib/new_relic/agent/instrumentation/grape/chain.rb +25 -0
  26. data/lib/new_relic/agent/instrumentation/grape/instrumentation.rb +100 -0
  27. data/lib/new_relic/agent/instrumentation/grape/prepend.rb +17 -0
  28. data/lib/new_relic/agent/instrumentation/httpclient.rb +8 -30
  29. data/lib/new_relic/agent/instrumentation/httpclient/chain.rb +25 -0
  30. data/lib/new_relic/agent/instrumentation/httpclient/instrumentation.rb +38 -0
  31. data/lib/new_relic/agent/instrumentation/httpclient/prepend.rb +17 -0
  32. data/lib/new_relic/agent/instrumentation/httprb.rb +29 -0
  33. data/lib/new_relic/agent/instrumentation/httprb/chain.rb +22 -0
  34. data/lib/new_relic/agent/instrumentation/httprb/instrumentation.rb +30 -0
  35. data/lib/new_relic/agent/instrumentation/httprb/prepend.rb +15 -0
  36. data/lib/new_relic/agent/instrumentation/memcache.rb +54 -69
  37. data/lib/new_relic/agent/instrumentation/memcache/chain.rb +16 -0
  38. data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +38 -121
  39. data/lib/new_relic/agent/instrumentation/memcache/helper.rb +56 -0
  40. data/lib/new_relic/agent/instrumentation/memcache/instrumentation.rb +88 -0
  41. data/lib/new_relic/agent/instrumentation/memcache/prepend.rb +88 -0
  42. data/lib/new_relic/agent/instrumentation/middleware_proxy.rb +2 -0
  43. data/lib/new_relic/agent/instrumentation/mongo.rb +7 -0
  44. data/lib/new_relic/agent/instrumentation/net_http.rb +39 -0
  45. data/lib/new_relic/agent/instrumentation/net_http/chain.rb +25 -0
  46. data/lib/new_relic/agent/instrumentation/{net_prepend.rb → net_http/instrumentation.rb} +3 -3
  47. data/lib/new_relic/agent/instrumentation/net_http/prepend.rb +21 -0
  48. data/lib/new_relic/agent/instrumentation/padrino.rb +18 -53
  49. data/lib/new_relic/agent/instrumentation/padrino/chain.rb +34 -0
  50. data/lib/new_relic/agent/instrumentation/padrino/instrumentation.rb +27 -0
  51. data/lib/new_relic/agent/instrumentation/padrino/prepend.rb +20 -0
  52. data/lib/new_relic/agent/instrumentation/rack.rb +29 -139
  53. data/lib/new_relic/agent/instrumentation/rack/chain.rb +57 -0
  54. data/lib/new_relic/agent/instrumentation/rack/helpers.rb +32 -0
  55. data/lib/new_relic/agent/instrumentation/rack/instrumentation.rb +73 -0
  56. data/lib/new_relic/agent/instrumentation/rack/prepend.rb +36 -0
  57. data/lib/new_relic/agent/instrumentation/rake.rb +13 -154
  58. data/lib/new_relic/agent/instrumentation/rake/chain.rb +25 -0
  59. data/lib/new_relic/agent/instrumentation/rake/instrumentation.rb +144 -0
  60. data/lib/new_relic/agent/instrumentation/rake/prepend.rb +14 -0
  61. data/lib/new_relic/agent/instrumentation/redis.rb +10 -109
  62. data/lib/new_relic/agent/instrumentation/redis/chain.rb +34 -0
  63. data/lib/new_relic/agent/instrumentation/redis/instrumentation.rb +65 -0
  64. data/lib/new_relic/agent/instrumentation/redis/prepend.rb +24 -0
  65. data/lib/new_relic/agent/instrumentation/resque.rb +8 -28
  66. data/lib/new_relic/agent/instrumentation/resque/chain.rb +22 -0
  67. data/lib/new_relic/agent/instrumentation/resque/instrumentation.rb +33 -0
  68. data/lib/new_relic/agent/instrumentation/resque/prepend.rb +16 -0
  69. data/lib/new_relic/agent/instrumentation/sinatra.rb +20 -158
  70. data/lib/new_relic/agent/instrumentation/sinatra/chain.rb +55 -0
  71. data/lib/new_relic/agent/instrumentation/sinatra/ignorer.rb +29 -34
  72. data/lib/new_relic/agent/instrumentation/sinatra/instrumentation.rb +118 -0
  73. data/lib/new_relic/agent/instrumentation/sinatra/prepend.rb +33 -0
  74. data/lib/new_relic/agent/instrumentation/typhoeus.rb +10 -89
  75. data/lib/new_relic/agent/instrumentation/typhoeus/chain.rb +22 -0
  76. data/lib/new_relic/agent/instrumentation/typhoeus/instrumentation.rb +82 -0
  77. data/lib/new_relic/agent/instrumentation/typhoeus/prepend.rb +14 -0
  78. data/lib/new_relic/agent/new_relic_service.rb +3 -12
  79. data/lib/new_relic/agent/sql_sampler.rb +1 -1
  80. data/lib/new_relic/agent/transaction.rb +1 -4
  81. data/lib/new_relic/control/frameworks/rails.rb +11 -9
  82. data/lib/new_relic/control/instance_methods.rb +1 -0
  83. data/lib/new_relic/dependency_detection.rb +116 -10
  84. data/lib/new_relic/noticed_error.rb +1 -5
  85. data/lib/new_relic/supportability_helper.rb +1 -2
  86. data/lib/new_relic/version.rb +2 -2
  87. data/newrelic_rpm.gemspec +1 -1
  88. metadata +53 -8
  89. data/cert/cacert.pem +0 -1177
  90. data/lib/new_relic/agent/instrumentation/http.rb +0 -49
  91. data/lib/new_relic/agent/instrumentation/net.rb +0 -70
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
4
+
5
+ module NewRelic::Agent::Instrumentation
6
+ module Sinatra
7
+ module Chain
8
+ def self.instrument!
9
+ ::Sinatra::Base.class_eval do
10
+ include ::NewRelic::Agent::Instrumentation::Sinatra::Tracer
11
+
12
+ def dispatch_with_newrelic
13
+ dispatch_with_tracing { dispatch_without_newrelic }
14
+ end
15
+ alias dispatch_without_newrelic dispatch!
16
+ alias dispatch! dispatch_with_newrelic
17
+
18
+ def process_route_with_newrelic(*args, &block)
19
+ process_route_with_tracing(*args) do
20
+ process_route_without_newrelic(*args, &block)
21
+ end
22
+ end
23
+ alias process_route_without_newrelic process_route
24
+ alias process_route process_route_with_newrelic
25
+
26
+ def route_eval_with_newrelic(*args, &block)
27
+ route_eval_with_tracing(*args) do
28
+ route_eval_without_newrelic(*args, &block)
29
+ end
30
+ end
31
+ alias route_eval_without_newrelic route_eval
32
+ alias route_eval route_eval_with_newrelic
33
+ end
34
+ end
35
+ end
36
+
37
+ module Build
38
+ module Chain
39
+ def self.instrument!
40
+ ::Sinatra::Base.class_eval do
41
+ class << self
42
+ def build_with_newrelic(*args, &block)
43
+ build_with_tracing(*args) do
44
+ build_without_newrelic(*args, &block)
45
+ end
46
+ end
47
+ alias build_without_newrelic build
48
+ alias build build_with_newrelic
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -2,49 +2,44 @@
2
2
  # This file is distributed under New Relic's license terms.
3
3
  # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
4
4
 
5
- module NewRelic
6
- module Agent
7
- module Instrumentation
8
- module Sinatra
9
- module Ignorer
5
+ module NewRelic::Agent::Instrumentation
6
+ module Sinatra
7
+ module Ignorer
10
8
 
11
- def self.should_ignore?(app, type)
12
- return false if !app.settings.respond_to?(:newrelic_ignores)
9
+ def self.should_ignore?(app, type)
10
+ return false if !app.settings.respond_to?(:newrelic_ignores)
13
11
 
14
- app.settings.newrelic_ignores[type].any? do |pattern|
15
- pattern.match(app.request.path_info)
16
- end
17
- end
18
-
19
- def newrelic_ignore(*routes)
20
- set_newrelic_ignore(:routes, *routes)
21
- end
12
+ app.settings.newrelic_ignores[type].any? do |pattern|
13
+ pattern.match(app.request.path_info)
14
+ end
15
+ end
22
16
 
23
- def newrelic_ignore_apdex(*routes)
24
- set_newrelic_ignore(:apdex, *routes)
25
- end
17
+ def newrelic_ignore(*routes)
18
+ set_newrelic_ignore(:routes, *routes)
19
+ end
26
20
 
27
- def newrelic_ignore_enduser(*routes)
28
- set_newrelic_ignore(:enduser, *routes)
29
- end
21
+ def newrelic_ignore_apdex(*routes)
22
+ set_newrelic_ignore(:apdex, *routes)
23
+ end
30
24
 
31
- private
25
+ def newrelic_ignore_enduser(*routes)
26
+ set_newrelic_ignore(:enduser, *routes)
27
+ end
32
28
 
33
- def set_newrelic_ignore(type, *routes)
34
- # Important to default this in the context of the actual app
35
- # If it's done at register time, ignores end up shared between apps.
36
- set :newrelic_ignores, Hash.new([]) if !respond_to?(:newrelic_ignores)
29
+ private
37
30
 
38
- # If we call an ignore without a route, it applies to the whole app
39
- routes = ["*"] if routes.empty?
31
+ def set_newrelic_ignore(type, *routes)
32
+ # Important to default this in the context of the actual app
33
+ # If it's done at register time, ignores end up shared between apps.
34
+ set :newrelic_ignores, Hash.new([]) if !respond_to?(:newrelic_ignores)
40
35
 
41
- settings.newrelic_ignores[type] += routes.map do |r|
42
- # Ugly sending to private Base#compile, but we want to mimic
43
- # exactly Sinatra's mapping of route text to regex
44
- Array(send(:compile, r)).first
45
- end
46
- end
36
+ # If we call an ignore without a route, it applies to the whole app
37
+ routes = ["*"] if routes.empty?
47
38
 
39
+ settings.newrelic_ignores[type] += routes.map do |r|
40
+ # Ugly sending to private Base#compile, but we want to mimic
41
+ # exactly Sinatra's mapping of route text to regex
42
+ Array(send(:compile, r)).first
48
43
  end
49
44
  end
50
45
  end
@@ -0,0 +1,118 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
4
+
5
+ # NewRelic instrumentation for Sinatra applications. Sinatra actions will
6
+ # appear in the UI similar to controller actions, and have breakdown charts
7
+ # and transaction traces.
8
+ #
9
+ # The actions in the UI will correspond to the pattern expression used
10
+ # to match them, not directly to full URL's.
11
+ module NewRelic::Agent::Instrumentation
12
+ module Sinatra
13
+ module Tracer
14
+ include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
15
+
16
+ def self.included(clazz)
17
+ clazz.extend(self)
18
+ end
19
+
20
+ # Expected method for supporting ControllerInstrumentation
21
+ def newrelic_request_headers(_)
22
+ request.env
23
+ end
24
+
25
+ def newrelic_middlewares
26
+ middlewares = [NewRelic::Rack::BrowserMonitoring]
27
+ if NewRelic::Rack::AgentHooks.needed?
28
+ middlewares << NewRelic::Rack::AgentHooks
29
+ end
30
+ middlewares
31
+ end
32
+
33
+ def build_with_tracing(*args, &block)
34
+ unless NewRelic::Agent.config[:disable_sinatra_auto_middleware]
35
+ newrelic_middlewares.each do |middleware_class|
36
+ try_to_use(self, middleware_class)
37
+ end
38
+ end
39
+ yield
40
+ end
41
+
42
+ def try_to_use(app, clazz)
43
+ has_middleware = app.middleware.any? { |info| info[0] == clazz }
44
+ app.use(clazz) unless has_middleware
45
+ end
46
+
47
+ # Capture last route we've seen. Will set for transaction on route_eval
48
+ def process_route_with_tracing(*args)
49
+ begin
50
+ env["newrelic.last_route"] = args[0]
51
+ rescue => e
52
+ ::NewRelic::Agent.logger.debug("Failed determining last route in Sinatra", e)
53
+ end
54
+ yield
55
+ end
56
+
57
+ # If a transaction name is already set, this call will tromple over it.
58
+ # This is intentional, as typically passing to a separate route is like
59
+ # an entirely separate transaction, so we pick up the new name.
60
+ #
61
+ # If we're ignored, this remains safe, since set_transaction_name
62
+ # care for the gating on the transaction's existence for us.
63
+ def route_eval_with_tracing(*args)
64
+ begin
65
+ if txn_name = TransactionNamer.transaction_name_for_route(env, request)
66
+ ::NewRelic::Agent::Transaction.set_default_transaction_name(
67
+ "#{self.class.name}/#{txn_name}", :sinatra)
68
+ end
69
+ rescue => e
70
+ ::NewRelic::Agent.logger.debug("Failed during route_eval to set transaction name", e)
71
+ end
72
+ yield
73
+ end
74
+
75
+ def get_request_params
76
+ begin
77
+ @request.params
78
+ rescue => e
79
+ NewRelic::Agent.logger.debug("Failed to get params from Rack request.", e)
80
+ nil
81
+ end
82
+ end
83
+
84
+ def dispatch_with_tracing
85
+ request_params = get_request_params
86
+ filtered_params = ::NewRelic::Agent::ParameterFiltering::apply_filters(request.env, request_params || {})
87
+
88
+ name = TransactionNamer.initial_transaction_name(request)
89
+ perform_action_with_newrelic_trace(:category => :sinatra,
90
+ :name => name,
91
+ :params => filtered_params) do
92
+ begin
93
+ yield
94
+ ensure
95
+ # Will only see an error raised if :show_exceptions is true, but
96
+ # will always see them in the env hash if they occur
97
+ had_error = env.has_key?('sinatra.error')
98
+ ::NewRelic::Agent.notice_error(env['sinatra.error']) if had_error
99
+ end
100
+ end
101
+ end
102
+
103
+ def do_not_trace?
104
+ Ignorer.should_ignore?(self, :routes)
105
+ end
106
+
107
+ # Overrides ControllerInstrumentation implementation
108
+ def ignore_apdex?
109
+ Ignorer.should_ignore?(self, :apdex)
110
+ end
111
+
112
+ # Overrides ControllerInstrumentation implementation
113
+ def ignore_enduser?
114
+ Ignorer.should_ignore?(self, :enduser)
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
4
+
5
+ module NewRelic::Agent::Instrumentation
6
+ module Sinatra
7
+ module Prepend
8
+ include ::NewRelic::Agent::Instrumentation::Sinatra::Tracer
9
+
10
+ def dispatch!
11
+ dispatch_with_tracing { super }
12
+ end
13
+
14
+ def process_route(*args, &block)
15
+ process_route_with_tracing(*args) { super }
16
+ end
17
+
18
+ def route_eval(*args, &block)
19
+ route_eval_with_tracing(*args) { super }
20
+ end
21
+ end
22
+
23
+ module Build
24
+ module Prepend
25
+ include ::NewRelic::Agent::Instrumentation::Sinatra::Tracer
26
+
27
+ def build(*args, &block)
28
+ build_with_tracing(*args) { super }
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -2,6 +2,10 @@
2
2
  # This file is distributed under New Relic's license terms.
3
3
  # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
4
4
 
5
+ require_relative 'typhoeus/instrumentation'
6
+ require_relative 'typhoeus/chain'
7
+ require_relative 'typhoeus/prepend'
8
+
5
9
  DependencyDetection.defer do
6
10
  named :typhoeus
7
11
 
@@ -10,7 +14,7 @@ DependencyDetection.defer do
10
14
  end
11
15
 
12
16
  depends_on do
13
- NewRelic::Agent::Instrumentation::TyphoeusTracing.is_supported_version?
17
+ NewRelic::Agent::Instrumentation::Typhoeus.is_supported_version?
14
18
  end
15
19
 
16
20
  executes do
@@ -22,7 +26,7 @@ DependencyDetection.defer do
22
26
  # Basic request tracing
23
27
  executes do
24
28
  Typhoeus.before do |request|
25
- NewRelic::Agent::Instrumentation::TyphoeusTracing.trace(request)
29
+ NewRelic::Agent::Instrumentation::Typhoeus.trace(request)
26
30
 
27
31
  # Ensure that we always return a truthy value from the before block,
28
32
  # otherwise Typhoeus will bail out of the instrumentation.
@@ -32,93 +36,10 @@ DependencyDetection.defer do
32
36
 
33
37
  # Apply single TT node for Hydra requests until async support
34
38
  executes do
35
- class Typhoeus::Hydra
36
-
37
- def run_with_newrelic(*args)
38
- segment = NewRelic::Agent::Tracer.start_segment(
39
- name: NewRelic::Agent::Instrumentation::TyphoeusTracing::HYDRA_SEGMENT_NAME
40
- )
41
-
42
- instance_variable_set :@__newrelic_hydra_segment, segment
43
-
44
- begin
45
- run_without_newrelic(*args)
46
- ensure
47
- segment.finish if segment
48
- end
49
- end
50
-
51
- alias run_without_newrelic run
52
- alias run run_with_newrelic
53
- end
54
- end
55
- end
56
-
57
-
58
- module NewRelic
59
- module Agent
60
- module Instrumentation
61
- module TyphoeusTracing
62
-
63
- HYDRA_SEGMENT_NAME = "External/Multiple/Typhoeus::Hydra/run"
64
- NOTICIBLE_ERROR_CLASS = "Typhoeus::Errors::TyphoeusError"
65
-
66
- EARLIEST_VERSION = Gem::Version.new("0.5.3")
67
- def self.is_supported_version?
68
- Gem::Version.new(Typhoeus::VERSION) >= NewRelic::Agent::Instrumentation::TyphoeusTracing::EARLIEST_VERSION
69
- end
70
-
71
- def self.request_is_hydra_enabled?(request)
72
- request.respond_to?(:hydra) && request.hydra
73
- end
74
-
75
- def self.response_message(response)
76
- if response.respond_to?(:response_message)
77
- response.response_message
78
- elsif response.respond_to?(:return_message)
79
- response.return_message
80
- else
81
- # 0.5.4 seems to have lost xxxx_message methods altogether.
82
- "timeout"
83
- end
84
- end
85
-
86
- def self.trace(request)
87
- state = NewRelic::Agent::Tracer.state
88
- return unless state.is_execution_traced?
89
-
90
- wrapped_request = ::NewRelic::Agent::HTTPClients::TyphoeusHTTPRequest.new(request)
91
-
92
- parent = if request_is_hydra_enabled?(request)
93
- request.hydra.instance_variable_get(:@__newrelic_hydra_segment)
94
- end
95
-
96
- segment = NewRelic::Agent::Tracer.start_external_request_segment(
97
- library: wrapped_request.type,
98
- uri: wrapped_request.uri,
99
- procedure: wrapped_request.method,
100
- parent: parent
101
- )
102
-
103
- segment.add_request_headers wrapped_request
104
-
105
- callback = Proc.new do
106
- wrapped_response = HTTPClients::TyphoeusHTTPResponse.new(request.response)
107
-
108
- segment.process_response_headers wrapped_response
109
-
110
- if request.response.code == 0
111
- segment.notice_error NoticibleError.new NOTICIBLE_ERROR_CLASS, response_message(request.response)
112
- end
113
-
114
- segment.finish if segment
115
- end
116
- request.on_complete.unshift(callback)
117
-
118
- rescue => e
119
- NewRelic::Agent.logger.error("Exception during trace setup for Typhoeus request", e)
120
- end
121
- end
39
+ if use_prepend?
40
+ prepend_instrument Typhoeus::Hydra, NewRelic::Agent::Instrumentation::Typhoeus::Prepend
41
+ else
42
+ chain_instrument NewRelic::Agent::Instrumentation::Typhoeus::Chain
122
43
  end
123
44
  end
124
45
  end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
4
+
5
+ module NewRelic::Agent::Instrumentation
6
+ module Typhoeus
7
+ module Chain
8
+ def self.instrument!
9
+ ::Typhoeus::Hydra.class_eval do
10
+ include NewRelic::Agent::Instrumentation::Typhoeus
11
+
12
+ def run_with_newrelic(*args)
13
+ with_tracing { run_without_newrelic(*args) }
14
+ end
15
+
16
+ alias run_without_newrelic run
17
+ alias run run_with_newrelic
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,82 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module Instrumentation
8
+ module Typhoeus
9
+
10
+ HYDRA_SEGMENT_NAME = "External/Multiple/Typhoeus::Hydra/run"
11
+ NOTICIBLE_ERROR_CLASS = "Typhoeus::Errors::TyphoeusError"
12
+
13
+ EARLIEST_VERSION = Gem::Version.new("0.5.3")
14
+
15
+ def self.is_supported_version?
16
+ Gem::Version.new(::Typhoeus::VERSION) >= EARLIEST_VERSION
17
+ end
18
+
19
+ def self.request_is_hydra_enabled?(request)
20
+ request.respond_to?(:hydra) && request.hydra
21
+ end
22
+
23
+ def self.response_message(response)
24
+ if response.respond_to?(:response_message)
25
+ response.response_message
26
+ elsif response.respond_to?(:return_message)
27
+ response.return_message
28
+ else
29
+ # 0.5.4 seems to have lost xxxx_message methods altogether.
30
+ "timeout"
31
+ end
32
+ end
33
+
34
+ def with_tracing
35
+ segment = NewRelic::Agent::Tracer.start_segment name: HYDRA_SEGMENT_NAME
36
+ instance_variable_set :@__newrelic_hydra_segment, segment
37
+ begin
38
+ yield
39
+ ensure
40
+ segment.finish if segment
41
+ end
42
+ end
43
+
44
+ def self.trace(request)
45
+ state = NewRelic::Agent::Tracer.state
46
+ return unless state.is_execution_traced?
47
+
48
+ wrapped_request = ::NewRelic::Agent::HTTPClients::TyphoeusHTTPRequest.new(request)
49
+
50
+ parent = if request_is_hydra_enabled?(request)
51
+ request.hydra.instance_variable_get(:@__newrelic_hydra_segment)
52
+ end
53
+
54
+ segment = NewRelic::Agent::Tracer.start_external_request_segment(
55
+ library: wrapped_request.type,
56
+ uri: wrapped_request.uri,
57
+ procedure: wrapped_request.method,
58
+ parent: parent
59
+ )
60
+
61
+ segment.add_request_headers wrapped_request
62
+
63
+ callback = Proc.new do
64
+ wrapped_response = HTTPClients::TyphoeusHTTPResponse.new(request.response)
65
+
66
+ segment.process_response_headers wrapped_response
67
+
68
+ if request.response.code == 0
69
+ segment.notice_error NoticibleError.new NOTICIBLE_ERROR_CLASS, response_message(request.response)
70
+ end
71
+
72
+ segment.finish if segment
73
+ end
74
+ request.on_complete.unshift(callback)
75
+
76
+ rescue => e
77
+ NewRelic::Agent.logger.error("Exception during trace setup for Typhoeus request", e)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end