class Datadog::Contrib::Excon::Middleware

Middleware implements an excon-middleware for ddtrace instrumentation

Constants

DEFAULT_ERROR_HANDLER

Public Class Methods

around_default_stack() click to toggle source

Returns a copy of the default stack with the trace middleware injected

# File lib/ddtrace/contrib/excon/middleware.rb, line 80
def self.around_default_stack
  ::Excon.defaults[:middlewares].dup.tap do |default_stack|
    # If the default stack contains a version of the trace middleware already...
    existing_trace_middleware = default_stack.find { |m| m <= Middleware }
    default_stack.delete(existing_trace_middleware) if existing_trace_middleware

    # Inject after the ResponseParser middleware
    response_middleware_index = default_stack.index(::Excon::Middleware::ResponseParser).to_i
    default_stack.insert(response_middleware_index + 1, self)
  end
end
new(stack, options = {}) click to toggle source
Calls superclass method
# File lib/ddtrace/contrib/excon/middleware.rb, line 23
def initialize(stack, options = {})
  super(stack)
  @default_options = datadog_configuration.options_hash.merge(options)
end
options() click to toggle source

rubocop:disable Style/TrivialAccessors

# File lib/ddtrace/contrib/excon/middleware.rb, line 63
def self.options
  @options
end
with(options = {}) click to toggle source

Returns a child class of this trace middleware With options given as defaults.

# File lib/ddtrace/contrib/excon/middleware.rb, line 58
def self.with(options = {})
  Class.new(self) do
    @options = options

    # rubocop:disable Style/TrivialAccessors
    def self.options
      @options
    end

    # default_options in this case contains our specific middleware options
    # so we want it to take precedence in build_request_options
    def build_request_options!(datum)
      datadog_configuration(datum[:host]).options_hash.merge(@default_options)
    end

    def initialize(stack)
      super(stack, self.class.options)
    end
  end
end

Public Instance Methods

build_request_options!(datum) click to toggle source

default_options in this case contains our specific middleware options so we want it to take precedence in build_request_options

# File lib/ddtrace/contrib/excon/middleware.rb, line 69
def build_request_options!(datum)
  datadog_configuration(datum[:host]).options_hash.merge(@default_options)
end
error_call(datum) click to toggle source
# File lib/ddtrace/contrib/excon/middleware.rb, line 51
def error_call(datum)
  handle_response(datum)
  @stack.error_call(datum)
end
request_call(datum) click to toggle source
# File lib/ddtrace/contrib/excon/middleware.rb, line 28
def request_call(datum)
  begin
    unless datum.key?(:datadog_span)
      @options = build_request_options!(datum)
      tracer.trace(Ext::SPAN_REQUEST).tap do |span|
        datum[:datadog_span] = span
        annotate!(span, datum)
        propagate!(span, datum) if distributed_tracing?
      end
    end
  rescue StandardError => e
    Datadog.logger.debug(e.message)
  end

  @stack.request_call(datum)
end
response_call(datum) click to toggle source
# File lib/ddtrace/contrib/excon/middleware.rb, line 45
def response_call(datum)
  @stack.response_call(datum).tap do |d|
    handle_response(d)
  end
end

Private Instance Methods

analytics_enabled?() click to toggle source
# File lib/ddtrace/contrib/excon/middleware.rb, line 98
def analytics_enabled?
  Contrib::Analytics.enabled?(@options[:analytics_enabled])
end
analytics_sample_rate() click to toggle source
# File lib/ddtrace/contrib/excon/middleware.rb, line 102
def analytics_sample_rate
  @options[:analytics_sample_rate]
end
annotate!(span, datum) click to toggle source
# File lib/ddtrace/contrib/excon/middleware.rb, line 114
def annotate!(span, datum)
  span.resource = datum[:method].to_s.upcase
  span.service = service_name(datum[:host], @options)
  span.span_type = Datadog::Ext::HTTP::TYPE_OUTBOUND

  # Tag as an external peer service
  span.set_tag(Datadog::Ext::Integration::TAG_PEER_SERVICE, span.service)

  # Set analytics sample rate
  Contrib::Analytics.set_sample_rate(span, analytics_sample_rate) if analytics_enabled?

  span.set_tag(Datadog::Ext::HTTP::URL, datum[:path])
  span.set_tag(Datadog::Ext::HTTP::METHOD, datum[:method].to_s.upcase)
  span.set_tag(Datadog::Ext::NET::TARGET_HOST, datum[:host])
  span.set_tag(Datadog::Ext::NET::TARGET_PORT, datum[:port])
end
datadog_configuration(host = :default) click to toggle source
# File lib/ddtrace/contrib/excon/middleware.rb, line 158
def datadog_configuration(host = :default)
  Datadog.configuration[:excon, host]
end
distributed_tracing?() click to toggle source
# File lib/ddtrace/contrib/excon/middleware.rb, line 106
def distributed_tracing?
  @options[:distributed_tracing] == true && tracer.enabled
end
error_handler() click to toggle source
# File lib/ddtrace/contrib/excon/middleware.rb, line 110
def error_handler
  @options[:error_handler] || DEFAULT_ERROR_HANDLER
end
handle_response(datum) click to toggle source
# File lib/ddtrace/contrib/excon/middleware.rb, line 131
def handle_response(datum)
  if datum.key?(:datadog_span)
    datum[:datadog_span].tap do |span|
      return span if span.finished?

      if datum.key?(:response)
        response = datum[:response]
        span.set_error(["Error #{response[:status]}", response[:body]]) if error_handler.call(response)
        span.set_tag(Datadog::Ext::HTTP::STATUS_CODE, response[:status])
      end
      span.set_error(datum[:error]) if datum.key?(:error)
      span.finish
      datum.delete(:datadog_span)
    end
  end
rescue StandardError => e
  Datadog.logger.debug(e.message)
end
propagate!(span, datum) click to toggle source
# File lib/ddtrace/contrib/excon/middleware.rb, line 150
def propagate!(span, datum)
  Datadog::HTTPPropagator.inject!(span.context, datum[:headers])
end
tracer() click to toggle source
# File lib/ddtrace/contrib/excon/middleware.rb, line 94
def tracer
  @options[:tracer]
end