lib/new_relic/agent/instrumentation/curb/instrumentation.rb in newrelic_rpm-8.2.0 vs lib/new_relic/agent/instrumentation/curb/instrumentation.rb in newrelic_rpm-8.3.0
- old
+ new
@@ -7,55 +7,54 @@
module Agent
module Instrumentation
module Curb
module Easy
attr_accessor :_nr_instrumented,
- :_nr_failure_instrumented,
- :_nr_http_verb,
- :_nr_header_str,
- :_nr_original_on_header,
- :_nr_original_on_complete,
- :_nr_original_on_failure,
- :_nr_serial
-
+ :_nr_failure_instrumented,
+ :_nr_http_verb,
+ :_nr_header_str,
+ :_nr_original_on_header,
+ :_nr_original_on_complete,
+ :_nr_original_on_failure,
+ :_nr_serial
+
# We have to hook these three methods separately, as they don't use
# Curl::Easy#http
def http_head_with_tracing
self._nr_http_verb = :HEAD
yield
end
-
+
def http_post_with_tracing
self._nr_http_verb = :POST
yield
end
-
-
+
def http_put_with_tracing
self._nr_http_verb = :PUT
yield
end
-
+
# Hook the #http method to set the verb.
def http_with_tracing verb
self._nr_http_verb = verb.to_s.upcase
yield
end
-
+
# Hook the #perform method to mark the request as non-parallel.
def perform_with_tracing
self._nr_http_verb ||= :GET
self._nr_serial = true
yield
end
-
+
# Record the HTTP verb for future #perform calls
def method_with_tracing verb
self._nr_http_verb = verb.upcase
yield
end
-
+
# We override this method in order to ensure access to header_str even
# though we use an on_header callback
def header_str_with_tracing
if self._nr_serial
self._nr_header_str
@@ -63,69 +62,67 @@
# Since we didn't install a header callback for a non-serial request,
# just fall back to the original implementation.
yield
end
end
-
end
-####################################################
+ ####################################################
module Multi
include NewRelic::Agent::MethodTracer
# Add CAT with callbacks if the request is serial
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
# Trace as an External/Multiple call if the first request isn't serial.
def perform_with_tracing
return yield if first_request_is_serial?
-
+
trace_execution_scoped("External/Multiple/Curb::Multi/perform") do
yield
end
end
# Instrument the specified +request+ (a Curl::Easy object)
# and set up cross-application tracing if it's enabled.
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
-
-
+
# 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
def wrap_request(request)
return NewRelic::Agent::HTTPClients::CurbRequest.new(request),
NewRelic::Agent::HTTPClients::CurbResponse.new(request)
end
-
+
# Install a callback that will record the response headers
# to enable CAT linking
def install_header_callback(request, wrapped_response)
original_callback = request.on_header
request._nr_original_on_header = original_callback
@@ -137,11 +134,11 @@
wrapped_response.append_header_data header_data
header_data.length
end
end
end
-
+
# Install a callback that will finish the trace.
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|
@@ -154,11 +151,11 @@
original_callback.call(finished_request) if original_callback
remove_instrumentation_callbacks(request)
end
end
end
-
+
# 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
# _nr_failure_instrumented exists to prevent infinitely chaining
@@ -175,48 +172,47 @@
end
ensure
original_callback.call(failed_request, error) if original_callback
remove_failure_callback(failed_request)
end
- request._nr_failure_instrumented = true
+ request._nr_failure_instrumented = true
end
end
-
+
# on_failure callbacks cannot be removed in the on_complete
# callback where this method is invoked because on_complete
# fires before the on_failure!
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
-
- # We execute customer's on_failure callback (if any) and
- # uninstall our hook here since the on_complete callback
+
+ # 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.
def remove_failure_callback(request)
request.on_failure(&request._nr_original_on_failure)
request._nr_failure_instrumented = false
end
-
+
private
-
+
def first_request_is_serial?
return false unless (first = self.requests.first)
-
+
# Before curb 0.9.8, requests was an array of Curl::Easy
# instances. Starting with 0.9.8, it's a Hash where the
# values are Curl::Easy instances.
#
# So, requests.first will either be an_obj or [a_key, an_obj].
# We need to handle either case.
#
first = first[-1] if first.is_a?(Array)
-
+
first.respond_to?(:_nr_serial) && first._nr_serial
end
-
end
end
end
end
-end
\ No newline at end of file
+end