Skip to content

Commit 9670a95

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 cfaa2b7 commit 9670a95

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
@@ -33,6 +33,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3333
([#236](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/236))
3434
- Add README and example app for Prometheus Remote Write Exporter
3535
([#227](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/227]))
36+
- `opentelemetry-instrumentation-requests` Use instanceof to check if responses are valid Response objects
37+
([#273](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/273))
3638

3739
### Changed
3840
- `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)