Skip to content

Commit bd51c21

Browse files
authored
Guard against various Faraday exception response formats (#1428)
* Fix randomly failing test by stubbing getconf shell out * Guard against other Faraday exception response formats * Fix tests for older Faraday versions * Update CHANGELOG
1 parent 5467b31 commit bd51c21

File tree

4 files changed

+89
-6
lines changed

4 files changed

+89
-6
lines changed

CHANGELOG.asciidoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ endif::[]
3434
[[release-notes-4.x]]
3535
=== Ruby Agent version 4.x
3636
37+
[float]
38+
===== Fixed
39+
- Guard against various Faraday exception response formats {pull}1428[#1428]
40+
3741
[[release-notes-4.7.0]]
3842
==== 4.7.0
3943

lib/elastic_apm/spies/faraday.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,14 @@ def run_request(method, url, body, headers, &block)
109109
yield req if block
110110
end
111111
rescue Faraday::ClientError, Faraday::ServerError => e # Faraday::Response::RaiseError
112-
status = e.response_status if e.respond_to?(:response_status)
113-
status ||= e.response&.fetch(:status)
112+
status =
113+
if e.respond_to?(:response_status)
114+
e.response_status
115+
elsif e.response && e.response.respond_to?(:status)
116+
e.response.status
117+
elsif e.response && e.response.respond_to?(:fetch)
118+
e.response[:status]
119+
end
114120
http = span&.context&.http
115121
if http && status
116122
http.status_code = status.to_s

spec/elastic_apm/metrics/cpu_mem_set_spec.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ module Metrics
4646
'system.memory.total': 4_042_711_040,
4747
'system.process.cpu.total.norm.pct': 0.2,
4848
'system.process.memory.size': 53_223_424,
49-
'system.process.memory.rss.bytes': 12_738_560
49+
'system.process.memory.rss.bytes': 25_477_120
5050
)
5151
end
5252

@@ -72,7 +72,7 @@ module Metrics
7272
'system.memory.total': 4_042_711_040,
7373
'system.process.cpu.total.norm.pct': 0.2,
7474
'system.process.memory.size': 53_223_424,
75-
'system.process.memory.rss.bytes': 12_738_560
75+
'system.process.memory.rss.bytes': 25_477_120
7676
)
7777
end
7878
end
@@ -100,6 +100,8 @@ def mock_proc_files(
100100
proc_stat_format: :debian,
101101
proc_meminfo_format: nil
102102
)
103+
allow_any_instance_of(ElasticAPM::Metrics::CpuMemSet::Linux::Meminfo).
104+
to receive(:`).with('getconf PAGESIZE').and_return('8192')
103105
{
104106
'/proc/stat' =>
105107
["proc_stat_#{proc_stat_format}", { user: user, idle: idle }],

spec/elastic_apm/spies/faraday_spec.rb

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ module ElasticAPM
198198
end
199199
end
200200

201-
it 'should capture status_code' do
201+
it 'captures status_code' do
202202
WebMock.stub_request(:get, 'http://example.com')
203203
.to_return(status: [404, 'Not Found'])
204204

@@ -217,7 +217,7 @@ module ElasticAPM
217217
expect(http.status_code).to match('404')
218218
end
219219

220-
it 'should handle a nil response' do
220+
it 'handles a nil response' do
221221
WebMock.stub_request(:get, 'http://example.com')
222222
.to_raise(Faraday::ClientError)
223223

@@ -235,6 +235,77 @@ module ElasticAPM
235235
expect(http.status_code).to be nil
236236
end
237237

238+
it 'handles faraday response' do
239+
class FaradayErrorWithResponseObject < Faraday::ClientError
240+
def response
241+
Faraday::Response.new(status: 500)
242+
end
243+
undef response_status
244+
end
245+
WebMock.stub_request(:get, 'http://example.com')
246+
.to_raise(FaradayErrorWithResponseObject.new(nil))
247+
248+
with_agent do
249+
begin
250+
ElasticAPM.with_transaction 'Faraday Middleware test' do
251+
client.get('http://example.com')
252+
end
253+
rescue Faraday::ClientError
254+
end
255+
end
256+
span, = @intercepted.spans
257+
258+
http = span.context.http
259+
expect(http.status_code).to eq('500')
260+
end
261+
262+
it 'handles faraday response hash' do
263+
class FaradayErrorWithResponseHash < Faraday::ClientError
264+
def response
265+
{ status: 500 }
266+
end
267+
undef response_status
268+
end
269+
WebMock.stub_request(:get, 'http://example.com')
270+
.to_raise(FaradayErrorWithResponseHash.new(nil))
271+
272+
with_agent do
273+
begin
274+
ElasticAPM.with_transaction 'Faraday Middleware test' do
275+
client.get('http://example.com')
276+
end
277+
rescue Faraday::ClientError
278+
end
279+
end
280+
span, = @intercepted.spans
281+
282+
http = span.context.http
283+
expect(http.status_code).to eq('500')
284+
end
285+
286+
it 'does not raise error when response is string' do
287+
class FaradayErrorWithResponseString < Faraday::ClientError
288+
def response
289+
'whatever'
290+
end
291+
undef response_status
292+
end
293+
WebMock.stub_request(:get, 'http://example.com')
294+
.to_raise(FaradayErrorWithResponseString.new(nil))
295+
296+
with_agent do
297+
begin
298+
ElasticAPM.with_transaction 'Faraday Middleware test' do
299+
client.get('http://example.com')
300+
end
301+
rescue Faraday::ClientError
302+
end
303+
end
304+
span, = @intercepted.spans
305+
306+
http = span.context.http
307+
expect(http.status_code).to be nil
308+
end
238309
end
239310
end
240311
end

0 commit comments

Comments
 (0)