From 308fadc64f4cbd9f4fbc83ae3a839c88cb5aaa23 Mon Sep 17 00:00:00 2001 From: Rytis Bagdziunas Date: Tue, 21 May 2024 19:22:57 +0200 Subject: [PATCH 1/5] Ensure httpx non-client methods are instrumented --- .../instrumentation/httpx/__init__.py | 4 ++-- .../tests/test_httpx_integration.py | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py b/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py index 7fcc7128be..aad5634844 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py @@ -564,11 +564,11 @@ def _instrument(self, **kwargs): tracer_provider = kwargs.get("tracer_provider") _InstrumentedClient._tracer_provider = tracer_provider _InstrumentedAsyncClient._tracer_provider = tracer_provider - httpx.Client = _InstrumentedClient + httpx.Client = httpx._api.Client = _InstrumentedClient httpx.AsyncClient = _InstrumentedAsyncClient def _uninstrument(self, **kwargs): - httpx.Client = self._original_client + httpx.Client = httpx._api.Client = self._original_client httpx.AsyncClient = self._original_async_client _InstrumentedClient._tracer_provider = None _InstrumentedClient._request_hook = None diff --git a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py index c3f668cafe..673936cb8c 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py @@ -532,12 +532,34 @@ def test_instrument_client(self): self.assertEqual(result.text, "Hello!") self.assert_span(num_spans=1) + def test_instrumentation_without_client(self): + + HTTPXClientInstrumentor().instrument() + results = [ + httpx.get(self.URL), + httpx.request("GET", self.URL), + ] + with httpx.stream("GET", self.URL) as stream: + stream.read() + results.append(stream) + + spans = self.assert_span(num_spans=len(results)) + for idx, res in enumerate(results): + self.assertEqual(res.text, "Hello!") + self.assertEqual( + spans[idx].attributes[SpanAttributes.HTTP_URL], self.URL + ) + + HTTPXClientInstrumentor().uninstrument() + def test_uninstrument(self): HTTPXClientInstrumentor().instrument() HTTPXClientInstrumentor().uninstrument() client = self.create_client() result = self.perform_request(self.URL, client=client) + result_no_client = httpx.get(self.URL) self.assertEqual(result.text, "Hello!") + self.assertEqual(result_no_client.text, "Hello!") self.assert_span(num_spans=0) def test_uninstrument_client(self): From 4f0a3650d735947178d4c79580d3c909fa8f4bb1 Mon Sep 17 00:00:00 2001 From: Rytis Bagdziunas Date: Tue, 21 May 2024 19:33:13 +0200 Subject: [PATCH 2/5] Update changelog --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17152f3fa7..54f20488fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,7 +42,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- `opentelemetry-instrumentation-dbapi` Fix compatibility with Psycopg3 to extract libpq build version (#2500)[https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2500] +- `opentelemetry-instrumentation-dbapi` Fix compatibility with Psycopg3 to extract libpq build version + ([#2500](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2500)) +- `opentelemetry-instrumentation-httpx` Ensure httpx.get or httpx.request like methods are instrumented + ([#1742](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2538)) - `opentelemetry-instrumentation-grpc` AioClientInterceptor should propagate with a Metadata object ([#2363](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2363)) - `opentelemetry-instrumentation-boto3sqs` Instrument Session and resource From d70f52ad1e39c1256999011df85e14eefcbc91ca Mon Sep 17 00:00:00 2001 From: Rytis Bagdziunas Date: Tue, 21 May 2024 22:05:38 +0200 Subject: [PATCH 3/5] Added subTest to distinguish tests inside a loop --- .../tests/test_httpx_integration.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py index 673936cb8c..d64db1a8f5 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py @@ -545,10 +545,12 @@ def test_instrumentation_without_client(self): spans = self.assert_span(num_spans=len(results)) for idx, res in enumerate(results): - self.assertEqual(res.text, "Hello!") - self.assertEqual( - spans[idx].attributes[SpanAttributes.HTTP_URL], self.URL - ) + with self.subTest(idx=idx, res=res): + self.assertEqual(res.text, "Hello!") + self.assertEqual( + spans[idx].attributes[SpanAttributes.HTTP_URL], + self.URL, + ) HTTPXClientInstrumentor().uninstrument() From cbebbbf447d7a00d8bfee2dbe254a774cad34a5f Mon Sep 17 00:00:00 2001 From: Rytis Bagdziunas Date: Tue, 21 May 2024 22:10:46 +0200 Subject: [PATCH 4/5] Updated changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54f20488fb..72ff7ac52c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,7 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `opentelemetry-instrumentation-dbapi` Fix compatibility with Psycopg3 to extract libpq build version ([#2500](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2500)) - `opentelemetry-instrumentation-httpx` Ensure httpx.get or httpx.request like methods are instrumented - ([#1742](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2538)) + ([#2538](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2538)) - `opentelemetry-instrumentation-grpc` AioClientInterceptor should propagate with a Metadata object ([#2363](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2363)) - `opentelemetry-instrumentation-boto3sqs` Instrument Session and resource From a6cd4aae8464f5e4ddfc49f54f304feda5fd9e58 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Thu, 30 May 2024 16:40:18 -0600 Subject: [PATCH 5/5] Add a comment explaining private attribute usage --- .../src/opentelemetry/instrumentation/httpx/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py b/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py index aad5634844..850e76eea3 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py @@ -564,6 +564,8 @@ def _instrument(self, **kwargs): tracer_provider = kwargs.get("tracer_provider") _InstrumentedClient._tracer_provider = tracer_provider _InstrumentedAsyncClient._tracer_provider = tracer_provider + # Intentionally using a private attribute here, see: + # https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2538#discussion_r1610603719 httpx.Client = httpx._api.Client = _InstrumentedClient httpx.AsyncClient = _InstrumentedAsyncClient