Module: NewRelic::Agent::Instrumentation::Curb::Multi
- Includes:
- MethodTracer
- Included in:
- Prepend
- Defined in:
- lib/new_relic/agent/instrumentation/curb/prepend.rb,
lib/new_relic/agent/instrumentation/curb/instrumentation.rb
Defined Under Namespace
Modules: Prepend
Constant Summary collapse
- INSTRUMENTATION_NAME =
'Curb'
Constants included from MethodTracer::ClassMethods::AddMethodTracer
MethodTracer::ClassMethods::AddMethodTracer::ALLOWED_KEYS, MethodTracer::ClassMethods::AddMethodTracer::DEFAULT_SETTINGS
Instance Method Summary collapse
-
#add_with_tracing(curl) ⇒ Object
Add CAT with callbacks if the request is serial.
-
#hook_pending_request(request) ⇒ Object
Instrument the specified
request
(a Curl::Easy object) and set up cross-application tracing if it’s enabled. -
#install_completion_callback(request, wrapped_response, segment) ⇒ Object
Install a callback that will finish the trace.
-
#install_failure_callback(request, _wrapped_response, segment) ⇒ Object
Install a callback that will fire on failures NOTE: on_failure is not always called, so we’re not always unhooking the callback.
-
#install_header_callback(request, wrapped_response) ⇒ Object
Install a callback that will record the response headers to enable CAT linking.
-
#perform_with_tracing ⇒ Object
Trace as an External/Multiple call if the first request isn’t serial.
-
#remove_failure_callback(request) ⇒ Object
We execute customer’s on_failure callback (if any) and uninstall our hook here since the on_complete callback fires before the on_failure callback.
-
#remove_instrumentation_callbacks(request) ⇒ Object
on_failure callbacks cannot be removed in the on_complete callback where this method is invoked because on_complete fires before the on_failure!.
-
#wrap_request(request) ⇒ Object
Create request and response adapter objects for the specified
request
NOTE: Although strange to wrap request and response at once, it works because curb’s callback mechanism updates the instantiated wrappers during the life-cycle of external request.
Methods included from MethodTracer
extended, included, #trace_execution_scoped, #trace_execution_unscoped
Methods included from MethodTracer::ClassMethods
#add_method_tracer, #remove_method_tracer
Methods included from MethodTracer::ClassMethods::AddMethodTracer
#_nr_clear_traced_methods!, #_nr_default_metric_name, #_nr_derived_class_name, #_nr_traced_method_module, #_nr_validate_method_tracer_options, #method_traced?, #newrelic_method_exists?
Instance Method Details
#add_with_tracing(curl) ⇒ Object
Add CAT with callbacks if the request is serial
74 75 76 77 78 79 80 |
# File 'lib/new_relic/agent/instrumentation/curb/instrumentation.rb', line 74 def add_with_tracing(curl) if curl.respond_to?(:_nr_serial) && curl._nr_serial hook_pending_request(curl) if NewRelic::Agent::Tracer.tracing_enabled? end return yield end |
#hook_pending_request(request) ⇒ Object
Instrument the specified request
(a Curl::Easy object) and set up cross-application tracing if it’s enabled.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/new_relic/agent/instrumentation/curb/instrumentation.rb', line 95 def hook_pending_request(request) wrapped_request, wrapped_response = wrap_request(request) segment = NewRelic::Agent::Tracer.start_external_request_segment( library: wrapped_request.type, uri: wrapped_request.uri, procedure: wrapped_request.method ) segment.add_request_headers(wrapped_request) # install all callbacks unless request._nr_instrumented install_header_callback(request, wrapped_response) install_completion_callback(request, wrapped_response, segment) install_failure_callback(request, wrapped_response, segment) request._nr_instrumented = true end rescue => err NewRelic::Agent.logger.error('Untrapped exception', err) end |
#install_completion_callback(request, wrapped_response, segment) ⇒ Object
Install a callback that will finish the trace.
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/new_relic/agent/instrumentation/curb/instrumentation.rb', line 143 def install_completion_callback(request, wrapped_response, segment) original_callback = request.on_complete request._nr_original_on_complete = original_callback request.on_complete do |finished_request| begin segment&.process_response_headers(wrapped_response) ensure ::NewRelic::Agent::Transaction::Segment.finish(segment) # Make sure the existing completion callback is run, and restore the # on_complete callback to how it was before. original_callback&.call(finished_request) remove_instrumentation_callbacks(request) end end end |
#install_failure_callback(request, _wrapped_response, segment) ⇒ Object
Install a callback that will fire on failures NOTE: on_failure is not always called, so we’re not always unhooking the callback. No harm/no foul in production, but definitely something to beware of if debugging callback issues our on_failure callback hook.
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/new_relic/agent/instrumentation/curb/instrumentation.rb', line 165 def install_failure_callback(request, _wrapped_response, segment) original_callback = request.on_failure nr_original_callback = original_callback.instance_variable_get(:@__newrelic_original_callback) original_callback = nr_original_callback || original_callback request._nr_original_on_failure = original_callback newrelic_callback = proc do |failed_request, error| begin if segment noticeable_error = NewRelic::Agent::NoticeableError.new(error[0].name, error[-1]) segment.notice_error(noticeable_error) end ensure original_callback&.call(failed_request, error) remove_failure_callback(failed_request) end end newrelic_callback.instance_variable_set(:@__newrelic_original_callback, original_callback) request.on_failure(&newrelic_callback) end |
#install_header_callback(request, wrapped_response) ⇒ Object
Install a callback that will record the response headers to enable CAT linking
128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/new_relic/agent/instrumentation/curb/instrumentation.rb', line 128 def install_header_callback(request, wrapped_response) original_callback = request.on_header request._nr_original_on_header = original_callback request._nr_header_str = nil request.on_header do |header_data| if original_callback original_callback.call(header_data) else wrapped_response.append_header_data(header_data) header_data.length end end end |
#perform_with_tracing ⇒ Object
Trace as an External/Multiple call if the first request isn’t serial.
83 84 85 86 87 88 89 90 91 |
# File 'lib/new_relic/agent/instrumentation/curb/instrumentation.rb', line 83 def perform_with_tracing return yield if first_request_is_serial? NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME) trace_execution_scoped('External/Multiple/Curb::Multi/perform') do yield end end |
#remove_failure_callback(request) ⇒ Object
We execute customer’s on_failure callback (if any) and uninstall our hook here since the on_complete callback fires before the on_failure callback.
201 202 203 |
# File 'lib/new_relic/agent/instrumentation/curb/instrumentation.rb', line 201 def remove_failure_callback(request) request.on_failure(&request._nr_original_on_failure) end |
#remove_instrumentation_callbacks(request) ⇒ Object
on_failure callbacks cannot be removed in the on_complete callback where this method is invoked because on_complete fires before the on_failure!
192 193 194 195 196 |
# File 'lib/new_relic/agent/instrumentation/curb/instrumentation.rb', line 192 def remove_instrumentation_callbacks(request) request.on_complete(&request._nr_original_on_complete) request.on_header(&request._nr_original_on_header) request._nr_instrumented = false end |
#wrap_request(request) ⇒ Object
Create request and response adapter objects for the specified request
NOTE: Although strange to wrap request and response at once, it works because curb’s callback mechanism updates the instantiated wrappers during the life-cycle of external request
121 122 123 124 |
# File 'lib/new_relic/agent/instrumentation/curb/instrumentation.rb', line 121 def wrap_request(request) return NewRelic::Agent::HTTPClients::CurbRequest.new(request), NewRelic::Agent::HTTPClients::CurbResponse.new(request) end |