From 96370866817adf3769ff0f8121f0ebb5311b2183 Mon Sep 17 00:00:00 2001 From: zqumei Date: Tue, 13 Jun 2023 00:19:00 -0400 Subject: [PATCH 1/9] feat: Add exclude urls feature to HTTPX instrumentation Issue: #539 --- CHANGELOG.md | 2 + .../pyproject.toml | 1 + .../instrumentation/httpx/__init__.py | 38 +++++++++++-- .../tests/test_httpx_integration.py | 55 +++++++++++++++++-- 4 files changed, 88 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1206844e55..9291f0a34c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added `exclude urls` feature to HTTPX instrumentation + ([#1900](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1900)) - `opentelemetry-resource-detector-azure` Add resource detectors for Azure App Service and VM ([#1901](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1901)) diff --git a/instrumentation/opentelemetry-instrumentation-httpx/pyproject.toml b/instrumentation/opentelemetry-instrumentation-httpx/pyproject.toml index a50b2f4754..50f3fccb74 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/pyproject.toml +++ b/instrumentation/opentelemetry-instrumentation-httpx/pyproject.toml @@ -38,6 +38,7 @@ test = [ "opentelemetry-instrumentation-httpx[instruments]", "opentelemetry-sdk ~= 1.12", "opentelemetry-test-utils == 0.42b0.dev", + "httpretty ~= 1.0", ] [project.entry-points.opentelemetry_instrumentor] 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 bb40adbc26..1ecf45967b 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py @@ -176,7 +176,13 @@ def response_hook(span, request, response): from opentelemetry.trace import SpanKind, TracerProvider, get_tracer from opentelemetry.trace.span import Span from opentelemetry.trace.status import Status +from opentelemetry.utils.http import ( + ExcludeList, + get_excluded_urls, + parse_excluded_urls, +) +_excluded_urls_from_env = get_excluded_urls("HTTPX") _logger = logging.getLogger(__name__) URL = typing.Tuple[bytes, bytes, typing.Optional[int], bytes] @@ -276,6 +282,7 @@ class SyncOpenTelemetryTransport(httpx.BaseTransport): right after the span is created response_hook: A hook that receives the span, request, and response that is called right before the span ends + excluded_urls: List of urls that should be excluded from tracing """ def __init__( @@ -284,6 +291,7 @@ def __init__( tracer_provider: typing.Optional[TracerProvider] = None, request_hook: typing.Optional[RequestHook] = None, response_hook: typing.Optional[ResponseHook] = None, + excluded_urls: typing.Optional[ExcludeList] = None, ): self._transport = transport self._tracer = get_tracer( @@ -293,6 +301,7 @@ def __init__( ) self._request_hook = request_hook self._response_hook = response_hook + self._excluded_urls = excluded_urls def __enter__(self) -> "SyncOpenTelemetryTransport": self._transport.__enter__() @@ -317,10 +326,13 @@ def handle_request( """Add request info to span.""" if context.get_value("suppress_instrumentation"): return self._transport.handle_request(*args, **kwargs) - method, url, headers, stream, extensions = _extract_parameters( args, kwargs ) + + if self._excluded_urls and self._excluded_urls.url_disabled(url): + return self._transport.handle_request(*args, **kwargs) + span_attributes = _prepare_attributes(method, url) request_info = RequestInfo(method, url, headers, stream, extensions) @@ -370,6 +382,7 @@ class AsyncOpenTelemetryTransport(httpx.AsyncBaseTransport): right after the span is created response_hook: A hook that receives the span, request, and response that is called right before the span ends + excluded_urls: List of urls that should be excluded from tracing """ def __init__( @@ -378,6 +391,7 @@ def __init__( tracer_provider: typing.Optional[TracerProvider] = None, request_hook: typing.Optional[RequestHook] = None, response_hook: typing.Optional[ResponseHook] = None, + excluded_urls: typing.Optional[ExcludeList] = None, ): self._transport = transport self._tracer = get_tracer( @@ -387,6 +401,7 @@ def __init__( ) self._request_hook = request_hook self._response_hook = response_hook + self._excluded_urls = excluded_urls async def __aenter__(self) -> "AsyncOpenTelemetryTransport": await self._transport.__aenter__() @@ -407,12 +422,16 @@ async def handle_async_request( httpx.Response, ]: """Add request info to span.""" - if context.get_value("suppress_instrumentation"): - return await self._transport.handle_async_request(*args, **kwargs) - method, url, headers, stream, extensions = _extract_parameters( args, kwargs ) + + if self._excluded_urls and self._excluded_urls.url_disabled(url): + return await self._transport.handle_async_request(*args, **kwargs) + + if context.get_value("suppress_instrumentation"): + return await self._transport.handle_async_request(*args, **kwargs) + span_attributes = _prepare_attributes(method, url) span_name = _get_default_span_name( @@ -459,6 +478,7 @@ class _InstrumentedClient(httpx.Client): _tracer_provider = None _request_hook = None _response_hook = None + _excluded_urls = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -478,6 +498,7 @@ class _InstrumentedAsyncClient(httpx.AsyncClient): _tracer_provider = None _request_hook = None _response_hook = None + _excluded_urls = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -513,11 +534,18 @@ def _instrument(self, **kwargs): right after the span is created ``response_hook``: A hook that receives the span, request, and response that is called right before the span ends + ``excluded_urls``: A string containing a comma-delimited + list of regexes used to exclude URLs from tracking """ self._original_client = httpx.Client self._original_async_client = httpx.AsyncClient request_hook = kwargs.get("request_hook") response_hook = kwargs.get("response_hook") + excluded_urls = kwargs.get("excluded_urls") + if excluded_urls is None: + excluded_urls = _excluded_urls_from_env + else: + excluded_urls = parse_excluded_urls(excluded_urls) if callable(request_hook): _InstrumentedClient._request_hook = request_hook _InstrumentedAsyncClient._request_hook = request_hook @@ -536,9 +564,11 @@ def _uninstrument(self, **kwargs): _InstrumentedClient._tracer_provider = None _InstrumentedClient._request_hook = None _InstrumentedClient._response_hook = None + _InstrumentedClient._excluded_urls = None _InstrumentedAsyncClient._tracer_provider = None _InstrumentedAsyncClient._request_hook = None _InstrumentedAsyncClient._response_hook = None + _InstrumentedAsyncClient._excluded_urls = None @staticmethod def instrument_client( diff --git a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py index daddaad306..9c12b30639 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py @@ -17,6 +17,7 @@ import typing from unittest import mock +import httpretty import httpx import respx @@ -43,10 +44,10 @@ ResponseHook, ResponseInfo, ) - from opentelemetry.sdk.trace.export import SpanExporter - from opentelemetry.trace import TracerProvider - from opentelemetry.trace.span import Span - +from opentelemetry.sdk.trace.export import SpanExporter +from opentelemetry.trace import TracerProvider +from opentelemetry.trace.span import Span +from opentelemetry.util.http import get_excluded_urls HTTP_RESPONSE_BODY = "http.response.body" @@ -380,8 +381,24 @@ def create_client( def setUp(self): super().setUp() + + self.env_patch = mock.patch.dict( + "os.environ", + { + "OTEL_PYTHON_HTTPX_EXCLUDED_URLS": "http://localhost/env_excluded_arg/123,env_excluded_noarg" + }, + ) + self.env_patch.start() + + self.exclude_patch = mock.patch( + "opentelemetry.instrumentation.httpx._excluded_urls_from_env", + get_excluded_urls("HTTPX"), + ) + self.exclude_patch.start() + HTTPXClientInstrumentor().instrument() self.client = self.create_client() + self.env_patch.stop() HTTPXClientInstrumentor().uninstrument() def test_custom_tracer_provider(self): @@ -495,6 +512,36 @@ def test_uninstrument(self): self.assertEqual(result.text, "Hello!") self.assert_span(num_spans=0) + def test_excluded_urls_explicit(self): + url_404 = "http://mock/status/404" + httpretty.register_uri( + httpretty.GET, + url_404, + status=404, + ) + + HTTPXClientInstrumentor().instrument(excluded_urls=".*/404") + client = self.create_client() + self.perform_request(self.URL) + self.perform_request(url_404) + + self.assert_span(num_spans=1) + + def test_excluded_urls_from_env(self): + url = "http://localhost/env_excluded_arg/123" + httpretty.register_uri( + httpretty.GET, + url, + status=200, + ) + + HTTPXClientInstrumentor().instrument() + client = self.create_client() + self.perform_request(self.URL) + self.perform_request(url) + + self.assert_span(num_spans=1) + def test_uninstrument_client(self): HTTPXClientInstrumentor().uninstrument_client(self.client) From 867b99f933b69a35fe66b50f1b10db4dca83390f Mon Sep 17 00:00:00 2001 From: Maciej Nachtygal Date: Thu, 6 Mar 2025 20:32:00 +0100 Subject: [PATCH 2/9] fix: overlooked typo and incorrect imports --- .../src/opentelemetry/instrumentation/httpx/__init__.py | 4 ++-- .../tests/test_httpx_integration.py | 9 +++++---- 2 files changed, 7 insertions(+), 6 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 303805bc38..b1774f3e87 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py @@ -781,7 +781,7 @@ def _handle_request_wrapper( # pylint: disable=too-many-locals ) if excluded_urls and excluded_urls.url_disabled(url): - return wrapeed(*args, **kwargs) + return wrapped(*args, **kwargs) method_original = method.decode() span_name = _get_default_span_name(method_original) @@ -860,7 +860,7 @@ async def _handle_async_request_wrapper( # pylint: disable=too-many-locals ) if excluded_urls and excluded_urls.url_disabled(url): - return await wrapeed(*args, **kwargs) + return await wrapped(*args, **kwargs) method_original = method.decode() span_name = _get_default_span_name(method_original) diff --git a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py index a8a6353d01..576abdb898 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py @@ -58,6 +58,7 @@ from opentelemetry.test.mock_textmap import MockTextMapPropagator from opentelemetry.test.test_base import TestBase from opentelemetry.trace import StatusCode +from opentelemetry.util.http import get_excluded_urls if typing.TYPE_CHECKING: from opentelemetry.instrumentation.httpx import ( @@ -68,10 +69,10 @@ ResponseHook, ResponseInfo, ) -from opentelemetry.sdk.trace.export import SpanExporter -from opentelemetry.trace import TracerProvider -from opentelemetry.trace.span import Span -from opentelemetry.util.http import get_excluded_urls + from opentelemetry.sdk.trace.export import SpanExporter + from opentelemetry.trace import TracerProvider + from opentelemetry.trace.span import Span + HTTP_RESPONSE_BODY = "http.response.body" From 0ed7895f15d4c6022a050ca5bc2932a9c80a8706 Mon Sep 17 00:00:00 2001 From: Maciej Nachtygal Date: Thu, 6 Mar 2025 20:33:49 +0100 Subject: [PATCH 3/9] docs: update changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c834de8fc8..75625616ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added `exclude urls` feature to HTTPX instrumentation + ([#3345](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3345)) - `opentelemetry-instrumentation-openai-v2` Update doc for OpenAI Instrumentation to support OpenAI Compatible Platforms ([#3279](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3279)) - `opentelemetry-instrumentation-system-metrics` Add `process` metrics and deprecated `process.runtime` prefixed ones @@ -537,8 +539,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Added `exclude urls` feature to HTTPX instrumentation - ([#1900](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1900)) - `opentelemetry-resource-detector-azure` Add resource detectors for Azure App Service and VM ([#1901](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1901)) - `opentelemetry-instrumentation-flask` Add support for Flask 3.0.0 From 9d3c296d55b7705cd2982abf2a5ea5f3eac49982 Mon Sep 17 00:00:00 2001 From: Maciej Nachtygal Date: Thu, 6 Mar 2025 21:24:19 +0100 Subject: [PATCH 4/9] refactor: streamline excluded_urls handling and remove redundant code --- .../pyproject.toml | 6 ------ .../instrumentation/httpx/__init__.py | 18 ++++++++++-------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-httpx/pyproject.toml b/instrumentation/opentelemetry-instrumentation-httpx/pyproject.toml index cc3d1bae6e..acb709ba0b 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/pyproject.toml +++ b/instrumentation/opentelemetry-instrumentation-httpx/pyproject.toml @@ -37,12 +37,6 @@ dependencies = [ instruments = [ "httpx >= 0.18.0", ] -test = [ - "opentelemetry-instrumentation-httpx[instruments]", - "opentelemetry-sdk ~= 1.12", - "opentelemetry-test-utils == 0.42b0.dev", - "httpretty ~= 1.0", -] [project.entry-points.opentelemetry_instrumentor] httpx = "opentelemetry.instrumentation.httpx:HTTPXClientInstrumentor" 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 b1774f3e87..c22c3fa16e 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py @@ -604,9 +604,6 @@ async def handle_async_request( if self._excluded_urls and self._excluded_urls.url_disabled(url): return await self._transport.handle_async_request(*args, **kwargs) - - if context.get_value("suppress_instrumentation"): - return await self._transport.handle_async_request(*args, **kwargs) method_original = method.decode() span_name = _get_default_span_name(method_original) @@ -715,11 +712,11 @@ def _instrument(self, **kwargs: typing.Any): else None ) - excluded_urls = kwargs.get("excluded_urls") - if excluded_urls is None: - excluded_urls = _excluded_urls_from_env - else: - excluded_urls = parse_excluded_urls(excluded_urls) + excluded_urls = ( + parse_excluded_urls(excluded_urls) + if kwargs.get("excluded_urls") + else _excluded_urls_from_env + ) _OpenTelemetrySemanticConventionStability._initialize() sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode( @@ -927,6 +924,7 @@ def instrument_client( tracer_provider: TracerProvider | None = None, request_hook: RequestHook | AsyncRequestHook | None = None, response_hook: ResponseHook | AsyncResponseHook | None = None, + excluded_urls: ExcludeList | None = None, ) -> None: """Instrument httpx Client or AsyncClient @@ -980,6 +978,7 @@ def instrument_client( sem_conv_opt_in_mode=sem_conv_opt_in_mode, request_hook=request_hook, response_hook=response_hook, + excluded_urls=excluded_urls, ), ) for transport in client._mounts.values(): @@ -993,6 +992,7 @@ def instrument_client( sem_conv_opt_in_mode=sem_conv_opt_in_mode, request_hook=request_hook, response_hook=response_hook, + excluded_urls=excluded_urls, ), ) client._is_instrumented_by_opentelemetry = True @@ -1006,6 +1006,7 @@ def instrument_client( sem_conv_opt_in_mode=sem_conv_opt_in_mode, async_request_hook=async_request_hook, async_response_hook=async_response_hook, + excluded_urls=excluded_urls, ), ) for transport in client._mounts.values(): @@ -1019,6 +1020,7 @@ def instrument_client( sem_conv_opt_in_mode=sem_conv_opt_in_mode, async_request_hook=async_request_hook, async_response_hook=async_response_hook, + excluded_urls=excluded_urls, ), ) client._is_instrumented_by_opentelemetry = True From 27e91f654100e5dc4e932a74036122e49e84722b Mon Sep 17 00:00:00 2001 From: Maciej Nachtygal Date: Thu, 6 Mar 2025 21:26:02 +0100 Subject: [PATCH 5/9] chore: bring back empty line --- .../src/opentelemetry/instrumentation/httpx/__init__.py | 1 + 1 file changed, 1 insertion(+) 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 c22c3fa16e..838518fe35 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py @@ -468,6 +468,7 @@ def handle_request( """Add request info to span.""" if not is_http_instrumentation_enabled(): return self._transport.handle_request(*args, **kwargs) + method, url, headers, stream, extensions = _extract_parameters( args, kwargs ) From 502d381a8db2c3a7c33aac48beacf81adc166e79 Mon Sep 17 00:00:00 2001 From: Maciej Nachtygal Date: Thu, 6 Mar 2025 21:42:23 +0100 Subject: [PATCH 6/9] feat: add httpretty to test requirements for httpx instrumentation --- .../opentelemetry-instrumentation-httpx/test-requirements-0.txt | 1 + .../opentelemetry-instrumentation-httpx/test-requirements-1.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-0.txt b/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-0.txt index b663f4566b..d0bd1a480d 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-0.txt +++ b/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-0.txt @@ -5,6 +5,7 @@ Deprecated==1.2.14 exceptiongroup==1.2.0 h11==0.12.0 httpcore==0.13.7 +httpretty==1.1.4 httpx==0.18.2 idna==3.7 iniconfig==2.0.0 diff --git a/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-1.txt b/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-1.txt index 4cd365d964..73d5b1ac5c 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-1.txt +++ b/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-1.txt @@ -5,6 +5,7 @@ Deprecated==1.2.14 exceptiongroup==1.2.0 h11==0.14.0 httpcore==1.0.4 +httpretty==1.1.4 httpx==0.27.0 idna==3.7 iniconfig==2.0.0 From be8edef16cd43ee2ecda51041baceef020751899 Mon Sep 17 00:00:00 2001 From: Maciej Nachtygal Date: Thu, 6 Mar 2025 21:42:39 +0100 Subject: [PATCH 7/9] fix: ensure url_disabled checks handle URLs as strings --- .../opentelemetry/instrumentation/httpx/__init__.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 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 838518fe35..78f8bc5106 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py @@ -233,11 +233,12 @@ async def async_response_hook(span, request, response): from opentelemetry.trace import SpanKind, Tracer, TracerProvider, get_tracer from opentelemetry.trace.span import Span from opentelemetry.trace.status import StatusCode -from opentelemetry.util.http import remove_url_credentials, sanitize_method -from opentelemetry.utils.http import ( +from opentelemetry.util.http import ( ExcludeList, get_excluded_urls, parse_excluded_urls, + remove_url_credentials, + sanitize_method, ) _excluded_urls_from_env = get_excluded_urls("HTTPX") @@ -473,7 +474,7 @@ def handle_request( args, kwargs ) - if self._excluded_urls and self._excluded_urls.url_disabled(url): + if self._excluded_urls and self._excluded_urls.url_disabled(str(url)): return self._transport.handle_request(*args, **kwargs) method_original = method.decode() @@ -603,7 +604,7 @@ async def handle_async_request( args, kwargs ) - if self._excluded_urls and self._excluded_urls.url_disabled(url): + if self._excluded_urls and self._excluded_urls.url_disabled(str(url)): return await self._transport.handle_async_request(*args, **kwargs) method_original = method.decode() @@ -778,7 +779,7 @@ def _handle_request_wrapper( # pylint: disable=too-many-locals args, kwargs ) - if excluded_urls and excluded_urls.url_disabled(url): + if excluded_urls and excluded_urls.url_disabled(str(url)): return wrapped(*args, **kwargs) method_original = method.decode() @@ -857,7 +858,7 @@ async def _handle_async_request_wrapper( # pylint: disable=too-many-locals args, kwargs ) - if excluded_urls and excluded_urls.url_disabled(url): + if excluded_urls and excluded_urls.url_disabled(str(url)): return await wrapped(*args, **kwargs) method_original = method.decode() From a26388e516343906b52d8608814ac9a408e28167 Mon Sep 17 00:00:00 2001 From: Maciej Nachtygal Date: Fri, 7 Mar 2025 11:05:12 +0100 Subject: [PATCH 8/9] fix: correctly handle excluded_urls from kwargs in HTTPXClientInstrumentor --- .../instrumentation/httpx/__init__.py | 6 ++-- .../tests/test_httpx_integration.py | 36 ++++--------------- 2 files changed, 11 insertions(+), 31 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 78f8bc5106..a39ee69be4 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py @@ -714,9 +714,11 @@ def _instrument(self, **kwargs: typing.Any): else None ) + excluded_urls_raw = kwargs.get("excluded_urls") + excluded_urls = ( - parse_excluded_urls(excluded_urls) - if kwargs.get("excluded_urls") + parse_excluded_urls(excluded_urls_raw) + if excluded_urls_raw else _excluded_urls_from_env ) diff --git a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py index 576abdb898..86072ff8ff 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py @@ -155,6 +155,7 @@ def setUp(self): self.env_patch = mock.patch.dict( "os.environ", { + "OTEL_PYTHON_HTTPX_EXCLUDED_URLS": "http://localhost/env_excluded_arg/123,env_excluded_noarg", OTEL_SEMCONV_STABILITY_OPT_IN: sem_conv_mode, }, ) @@ -749,22 +750,8 @@ def get_transport_handler(self, transport): def setUp(self): super().setUp() - self.env_patch = mock.patch.dict( - "os.environ", - { - "OTEL_PYTHON_HTTPX_EXCLUDED_URLS": "http://localhost/env_excluded_arg/123,env_excluded_noarg" - }, - ) - self.env_patch.start() - - self.exclude_patch = mock.patch( - "opentelemetry.instrumentation.httpx._excluded_urls_from_env", - get_excluded_urls("HTTPX"), - ) - self.exclude_patch.start() self.client = self.create_client() HTTPXClientInstrumentor().instrument_client(self.client) - self.env_patch.stop() def tearDown(self): HTTPXClientInstrumentor().uninstrument() @@ -973,31 +960,22 @@ def test_uninstrument(self): def test_excluded_urls_explicit(self): url_404 = "http://mock/status/404" - httpretty.register_uri( - httpretty.GET, - url_404, - status=404, - ) + respx.get(url_404).mock(httpx.Response(404)) HTTPXClientInstrumentor().instrument(excluded_urls=".*/404") client = self.create_client() - self.perform_request(self.URL) - self.perform_request(url_404) + self.perform_request(self.URL, client=client) + self.perform_request(url_404, client=client) self.assert_span(num_spans=1) def test_excluded_urls_from_env(self): url = "http://localhost/env_excluded_arg/123" - httpretty.register_uri( - httpretty.GET, - url, - status=200, - ) - + respx.get(url=url).mock(httpx.Response(200)) HTTPXClientInstrumentor().instrument() client = self.create_client() - self.perform_request(self.URL) - self.perform_request(url) + self.perform_request(self.URL, client=client) + self.perform_request(url, client=client) self.assert_span(num_spans=1) From c8cc1464b69ab0e62e722bf4829881d75c6af3af Mon Sep 17 00:00:00 2001 From: Maciej Nachtygal Date: Fri, 7 Mar 2025 11:08:08 +0100 Subject: [PATCH 9/9] chore: remove httpreety --- .../opentelemetry-instrumentation-httpx/test-requirements-0.txt | 1 - .../opentelemetry-instrumentation-httpx/test-requirements-1.txt | 1 - .../tests/test_httpx_integration.py | 1 - 3 files changed, 3 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-0.txt b/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-0.txt index d0bd1a480d..b663f4566b 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-0.txt +++ b/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-0.txt @@ -5,7 +5,6 @@ Deprecated==1.2.14 exceptiongroup==1.2.0 h11==0.12.0 httpcore==0.13.7 -httpretty==1.1.4 httpx==0.18.2 idna==3.7 iniconfig==2.0.0 diff --git a/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-1.txt b/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-1.txt index 73d5b1ac5c..4cd365d964 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-1.txt +++ b/instrumentation/opentelemetry-instrumentation-httpx/test-requirements-1.txt @@ -5,7 +5,6 @@ Deprecated==1.2.14 exceptiongroup==1.2.0 h11==0.14.0 httpcore==1.0.4 -httpretty==1.1.4 httpx==0.27.0 idna==3.7 iniconfig==2.0.0 diff --git a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py index 86072ff8ff..4b345eb09e 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py @@ -19,7 +19,6 @@ import typing from unittest import mock -import httpretty import httpx import respx from wrapt import ObjectProxy