lib/ddtrace/contrib/http/instrumentation.rb in ddtrace-0.20.0 vs lib/ddtrace/contrib/http/instrumentation.rb in ddtrace-0.21.0

- old
+ new

@@ -2,10 +2,11 @@ require 'ddtrace/pin' require 'ddtrace/ext/app_types' require 'ddtrace/ext/http' require 'ddtrace/ext/net' require 'ddtrace/ext/distributed' +require 'ddtrace/contrib/analytics' module Datadog module Contrib module HTTP # Instrumentation for Net::HTTP @@ -20,10 +21,21 @@ else base.send(:prepend, InstanceMethods) end end + # Span hook invoked after request is completed. + def self.after_request(&block) + if block_given? + # Set hook + @after_request = block + else + # Get hook + @after_request ||= nil + end + end + # Compatibility shim for Rubies not supporting `.prepend` module InstanceMethodsCompatibility def self.included(base) base.class_eval do alias_method :request_without_datadog, :request @@ -36,11 +48,10 @@ end end # InstanceMethods - implementing instrumentation module InstanceMethods - # rubocop:disable Metrics/MethodLength def request(req, body = nil, &block) # :yield: +response+ pin = datadog_pin return super(req, body, &block) unless pin && pin.tracer transport = pin.tracer.writer.transport @@ -51,16 +62,11 @@ pin.tracer.trace(Ext::SPAN_REQUEST) do |span| begin span.service = pin.service span.span_type = Datadog::Ext::HTTP::TYPE - span.resource = req.method - # Using the method as a resource, as URL/path can trigger - # a possibly infinite number of resources. - span.set_tag(Datadog::Ext::HTTP::URL, req.path) - span.set_tag(Datadog::Ext::HTTP::METHOD, req.method) if pin.tracer.enabled && !Datadog::Contrib::HTTP.should_skip_distributed_tracing?(pin) req.add_field(Datadog::Ext::DistributedTracing::HTTP_HEADER_TRACE_ID, span.trace_id) req.add_field(Datadog::Ext::DistributedTracing::HTTP_HEADER_PARENT_ID, span.span_id) if span.context.sampling_priority @@ -73,36 +79,65 @@ rescue StandardError => e Datadog::Tracer.log.error("error preparing span for http request: #{e}") ensure response = super(req, body, &block) end - span.set_tag(Datadog::Ext::HTTP::STATUS_CODE, response.code) - if req.respond_to?(:uri) && req.uri - span.set_tag(Datadog::Ext::NET::TARGET_HOST, req.uri.host) - span.set_tag(Datadog::Ext::NET::TARGET_PORT, req.uri.port.to_s) - else - span.set_tag(Datadog::Ext::NET::TARGET_HOST, @address) - span.set_tag(Datadog::Ext::NET::TARGET_PORT, @port.to_s) - end - case response.code.to_i / 100 - when 4 - span.set_error(response) - when 5 - span.set_error(response) + # Add additional tags to the span. + annotate_span!(span, req, response) + + # Invoke hook, if set. + unless Contrib::HTTP::Instrumentation.after_request.nil? + Contrib::HTTP::Instrumentation.after_request.call(span, self, req, response) end response end end + def annotate_span!(span, request, response) + span.set_tag(Datadog::Ext::HTTP::URL, request.path) + span.set_tag(Datadog::Ext::HTTP::METHOD, request.method) + span.set_tag(Datadog::Ext::HTTP::STATUS_CODE, response.code) + + if request.respond_to?(:uri) && request.uri + span.set_tag(Datadog::Ext::NET::TARGET_HOST, request.uri.host) + span.set_tag(Datadog::Ext::NET::TARGET_PORT, request.uri.port.to_s) + else + span.set_tag(Datadog::Ext::NET::TARGET_HOST, @address) + span.set_tag(Datadog::Ext::NET::TARGET_PORT, @port.to_s) + end + + # Set analytics sample rate + Contrib::Analytics.set_sample_rate(span, analytics_sample_rate) if analytics_enabled? + + case response.code.to_i + when 400...599 + span.set_error(response) + end + end + def datadog_pin @datadog_pin ||= begin service = Datadog.configuration[:http][:service_name] tracer = Datadog.configuration[:http][:tracer] Datadog::Pin.new(service, app: Ext::APP, app_type: Datadog::Ext::AppTypes::WEB, tracer: tracer) end + end + + private + + def datadog_configuration + Datadog.configuration[:http] + end + + def analytics_enabled? + Contrib::Analytics.enabled?(datadog_configuration[:analytics_enabled]) + end + + def analytics_sample_rate + datadog_configuration[:analytics_sample_rate] end end end end end