Skip to content

FaradaySpy -> missing response.status_code when using Faraday::Response::RaiseError middleware #1358

@ericproulx

Description

@ericproulx

Describe the bug

If a Faraday::Connection includes the RaiseError middleware, the response.status_code is not set in the span. By using this middleware, client's code is probably rescuing Faraday::Error and Faraday's run_request won't return a Faraday::Response.

Steps to reproduce

This test should fail.

# spec/elastic_apm/spies/faraday_spec.rb describe 'faraday middleware' do let(:faraday_connection) do Faraday.new do |builder| builder.use Faraday::Response::RaiseError builder.adapter :test do |stub| stub.get('/not_found') do |env| [ 404, { 'Content-Type': 'application/plain', }, 'Not Found' ] end end end end it 'should capture status_code' do with_agent do ElasticAPM.with_transaction 'Faraday test' do faraday_connection.get('/not_found') end end span, = @intercepted.spans http = span.context.http expect(http.status_code).to match('404') end end

Expected behavior

response.status_code should be set.

Environment

  • OS: Linux
  • Ruby version: 2.6.6
  • Framework and version: Rails 5.2.8.1
  • APM Server version: 7.17.5
  • Agent version: 3.15.1

Additional context

FaradaySpy should inject a middleware in the Faraday's Connection stack instead on relying on a Faraday::Response. It should be more reliable.

I've created one locally and it works

# elastic_apm/spies/faraday.rb ElasticAPM::Spies::FaradaySpy.without_net_http do trace_context = span&.trace_context || transaction.trace_context self.response :elastic_apm_span_middleware, span # middleware run_request_without_apm(method, url, body, headers) do |req| trace_context.apply_headers { |k, v| req[k] = v } yield req if block_given? end end ... class ApmSpanMiddleware < Faraday::Middleware attr_reader :span def initialize(app, span = nil, options = {}) super(app) @span = span end def on_complete(env) status = env[:status] http = span&.context&.http http.status_code = status.to_s if http && status span&.outcome = Span::Outcome.from_http_status(status) end end Faraday::Response.register_middleware elastic_apm_span_middleware: -> { ElasticAPM::Spies::ApmSpanMiddleware }
  • Agent config options

    Click to expand
    replace this line with your agent config options remember to mask any sensitive fields like tokens 

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions