Skip to content

Commit 645aec5

Browse files
author
David Grochowski
committed
Use instanceof to check if responses are valid Response objects
There are some exception types that set the response attribute to a non-Response type, e.g. "AttributeError: 'dict' object has no attribute 'status_code'"
1 parent 8abed07 commit 645aec5

File tree

3 files changed

+46
-1
lines changed

3 files changed

+46
-1
lines changed

Diff for: CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3737
([#227](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/227]))
3838
- `opentelemetry-instrumentation-botocore` Adds a field to report the number of retries it take to complete an API call
3939
([#275](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/275))
40+
- `opentelemetry-instrumentation-requests` Use instanceof to check if responses are valid Response objects
41+
([#273](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/273))
4042

4143
### Changed
4244
- `opentelemetry-instrumentation-asgi`, `opentelemetry-instrumentation-wsgi` Return `None` for `CarrierGetter` if key not found

Diff for: instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
from requests import Timeout, URLRequired
4040
from requests.exceptions import InvalidSchema, InvalidURL, MissingSchema
41+
from requests.models import Response
4142
from requests.sessions import Session
4243
from requests.structures import CaseInsensitiveDict
4344

@@ -158,7 +159,7 @@ def _instrumented_requests_call(
158159
finally:
159160
context.detach(token)
160161

161-
if result is not None:
162+
if isinstance(result, Response):
162163
if span.is_recording():
163164
span.set_attribute(
164165
"http.status_code", result.status_code

Diff for: instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py

+42
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@
2828
from opentelemetry.trace.status import StatusCode
2929

3030

31+
class InvalidResponseObjectException(Exception):
32+
def __init__(self):
33+
super().__init__()
34+
self.response = {}
35+
36+
3137
class RequestsIntegrationTestBase(abc.ABC):
3238
# pylint: disable=no-member
3339

@@ -307,6 +313,42 @@ def test_requests_exception_without_response(self, *_, **__):
307313
mocked_response.status_code = 500
308314
mocked_response.reason = "Internal Server Error"
309315

316+
@mock.patch(
317+
"requests.adapters.HTTPAdapter.send",
318+
side_effect=InvalidResponseObjectException,
319+
)
320+
def test_requests_exception_without_proper_response_type(self, *_, **__):
321+
with self.assertRaises(InvalidResponseObjectException):
322+
self.perform_request(self.URL)
323+
324+
span = self.assert_span()
325+
self.assertEqual(
326+
span.attributes,
327+
{"component": "http", "http.method": "GET", "http.url": self.URL},
328+
)
329+
self.assertEqual(span.status.status_code, StatusCode.ERROR)
330+
331+
self.assertIsNotNone(RequestsInstrumentor().meter)
332+
self.assertEqual(len(RequestsInstrumentor().meter.instruments), 1)
333+
recorder = list(RequestsInstrumentor().meter.instruments.values())[0]
334+
match_key = get_dict_as_key(
335+
{
336+
"http.method": "GET",
337+
"http.url": "http://httpbin.org/status/200",
338+
}
339+
)
340+
for key in recorder.bound_instruments.keys():
341+
self.assertEqual(key, match_key)
342+
# pylint: disable=protected-access
343+
bound = recorder.bound_instruments.get(key)
344+
for view_data in bound.view_datas:
345+
self.assertEqual(view_data.labels, key)
346+
self.assertEqual(view_data.aggregator.current.count, 1)
347+
348+
mocked_response = requests.Response()
349+
mocked_response.status_code = 500
350+
mocked_response.reason = "Internal Server Error"
351+
310352
@mock.patch(
311353
"requests.adapters.HTTPAdapter.send",
312354
side_effect=requests.RequestException(response=mocked_response),

0 commit comments

Comments
 (0)