module ElasticAPM::Spies::FaradaySpy::Ext

def run_request(method, url, body, headers, &block)

rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
def run_request(method, url, body, headers, &block)
  unless (transaction = ElasticAPM.current_transaction)
    return super(method, url, body, headers, &block)
  end
  uri = URI(build_url(url))
  # If url is set inside block it isn't available until yield,
  # so we temporarily build the request to yield. This could be a
  # problem if the block has side effects as it will be yielded twice
  # ~mikker
  unless uri.host
    tmp_request = build_request(method) do |req|
      yield(req) if block_given?
    end
    uri = tmp_request.path && URI(tmp_request.path)
  end
  host = uri&.host || 'localhost'
  upcased_method = method.to_s.upcase
  if uri
    destination = ElasticAPM::Span::Context::Destination.from_uri(uri)
    context =
      ElasticAPM::Span::Context.new(
        http: { url: uri, method: upcased_method },
        destination: destination
      )
  else
    context =
      ElasticAPM::Span::Context.new(http: { url: uri, method: upcased_method })
  end
  context =
    ElasticAPM::Span::Context.new(
      http: { url: uri, method: upcased_method },
      destination: destination
    )
  ElasticAPM.with_span(
    "#{upcased_method} #{host}",
    TYPE,
    subtype: SUBTYPE,
    action: upcased_method,
    context: context
  ) do |span|
    ElasticAPM::Spies::FaradaySpy.without_net_http do
      trace_context = span&.trace_context || transaction.trace_context
      result = super(method, url, body, headers) do |req|
        trace_context.apply_headers { |k, v| req[k] = v }
        yield req if block
      end
      if (http = span&.context&.http)
        http.status_code = result.status.to_s
      end
      span&.outcome = Span::Outcome.from_http_status(result.status)
      result
    end
  end
end